/src/main/webapp/app/**/@(*.)@(spec.ts)'],
26 | testEnvironmentOptions: {
27 | url: 'http://localhost:8080',
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/ngsw-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/service-worker/config/schema.json",
3 | "index": "/index.html",
4 | "assetGroups": [
5 | {
6 | "name": "app",
7 | "installMode": "prefetch",
8 | "resources": {
9 | "files": ["/favicon.ico", "/index.html", "/manifest.webapp", "/*.css", "/*.js"]
10 | }
11 | },
12 | {
13 | "name": "assets",
14 | "installMode": "lazy",
15 | "updateMode": "prefetch",
16 | "resources": {
17 | "files": ["/content/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"]
18 | }
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/npmw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | basedir=`dirname "$0"`
4 |
5 | if [ -f "$basedir/mvnw" ]; then
6 | bindir="$basedir/target/node"
7 | repodir="$basedir/target/node/node_modules"
8 | installCommand="$basedir/mvnw --batch-mode -ntp -Pwebapp frontend:install-node-and-npm@install-node-and-npm"
9 |
10 | PATH="$basedir/$builddir/:$PATH"
11 | NPM_EXE="$basedir/$builddir/node_modules/npm/bin/npm-cli.js"
12 | NODE_EXE="$basedir/$builddir/node"
13 | elif [ -f "$basedir/gradlew" ]; then
14 | bindir="$basedir/build/node/bin"
15 | repodir="$basedir/build/node/lib/node_modules"
16 | installCommand="$basedir/gradlew npmSetup"
17 | else
18 | echo "Using npm installed globally"
19 | exec npm "$@"
20 | fi
21 |
22 | NPM_EXE="$repodir/npm/bin/npm-cli.js"
23 | NODE_EXE="$bindir/node"
24 |
25 | if [ ! -x "$NPM_EXE" ] || [ ! -x "$NODE_EXE" ]; then
26 | $installCommand || true
27 | fi
28 |
29 | if [ -x "$NODE_EXE" ]; then
30 | echo "Using node installed locally $($NODE_EXE --version)"
31 | PATH="$bindir:$PATH"
32 | else
33 | NODE_EXE='node'
34 | fi
35 |
36 | if [ ! -x "$NPM_EXE" ]; then
37 | echo "Local npm not found, using npm installed globally"
38 | npm "$@"
39 | else
40 | echo "Using npm installed locally $($NODE_EXE $NPM_EXE --version)"
41 | $NODE_EXE $NPM_EXE "$@"
42 | fi
43 |
--------------------------------------------------------------------------------
/npmw.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | setlocal
4 |
5 | set NPMW_DIR=%~dp0
6 |
7 | if exist "%NPMW_DIR%mvnw.cmd" (
8 | set NODE_EXE=^"^"
9 | set NODE_PATH=%NPMW_DIR%target\node\
10 | set NPM_EXE=^"%NPMW_DIR%target\node\npm.cmd^"
11 | set INSTALL_NPM_COMMAND=^"%NPMW_DIR%mvnw.cmd^" -Pwebapp frontend:install-node-and-npm@install-node-and-npm
12 | ) else (
13 | set NODE_EXE=^"%NPMW_DIR%build\node\bin\node.exe^"
14 | set NODE_PATH=%NPMW_DIR%build\node\bin\
15 | set NPM_EXE=^"%NPMW_DIR%build\node\lib\node_modules\npm\bin\npm-cli.js^"
16 | set INSTALL_NPM_COMMAND=^"%NPMW_DIR%gradlew.bat^" npmSetup
17 | )
18 |
19 | if not exist %NPM_EXE% (
20 | call %INSTALL_NPM_COMMAND%
21 | )
22 |
23 | if exist %NODE_EXE% (
24 | Rem execute local npm with local node, whilst adding local node location to the PATH for this CMD session
25 | endlocal & echo "%PATH%"|find /i "%NODE_PATH%;">nul || set "PATH=%NODE_PATH%;%PATH%" & call %NODE_EXE% %NPM_EXE% %*
26 | ) else if exist %NPM_EXE% (
27 | Rem execute local npm, whilst adding local npm location to the PATH for this CMD session
28 | endlocal & echo "%PATH%"|find /i "%NODE_PATH%;">nul || set "PATH=%NODE_PATH%;%PATH%" & call %NPM_EXE% %*
29 | ) else (
30 | call npm %*
31 | )
32 |
--------------------------------------------------------------------------------
/src/main/docker/app.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | app:
5 | image: web
6 | environment:
7 | - _JAVA_OPTIONS=-Xmx512m -Xms256m
8 | - SPRING_PROFILES_ACTIVE=prod,api-docs
9 | - MANAGEMENT_PROMETHEUS_METRICS_EXPORT_ENABLED=true
10 | - SPRING_DATA_MONGODB_URI=mongodb://mongodb:27017/web
11 | ports:
12 | - 127.0.0.1:8080:8080
13 | healthcheck:
14 | test:
15 | - CMD
16 | - curl
17 | - -f
18 | - http://localhost:8080/management/health
19 | interval: 5s
20 | timeout: 5s
21 | retries: 40
22 | depends_on:
23 | mongodb:
24 | condition: service_healthy
25 | mongodb:
26 | extends:
27 | file: ./mongodb.yml
28 | service: mongodb
29 |
--------------------------------------------------------------------------------
/src/main/docker/grafana/provisioning/dashboards/dashboard.yml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | providers:
4 | - name: 'Prometheus'
5 | orgId: 1
6 | folder: ''
7 | type: file
8 | disableDeletion: false
9 | editable: true
10 | options:
11 | path: /etc/grafana/provisioning/dashboards
12 |
--------------------------------------------------------------------------------
/src/main/docker/mongodb-cluster.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | mongodb:
5 | image: mongo:7.0.6
6 | # If you want to expose these ports outside your dev PC,
7 | # remove the "127.0.0.1:" prefix
8 | ports:
9 | - 127.0.0.1:27017:27017
10 | command: mongos --configdb csvr/web-mongodb-config --bind_ip 0.0.0.0
11 | mongodb-node:
12 | build:
13 | context: .
14 | dockerfile: mongodb/MongoDB.Dockerfile
15 | command: mongod --shardsvr --replSet rs1
16 | mongodb-config:
17 | image: mongo:7.0.6
18 | container_name: web-mongodb-config
19 | command: mongod --configsvr --dbpath /data/db --replSet csvr
20 |
--------------------------------------------------------------------------------
/src/main/docker/mongodb.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | mongodb:
5 | image: mongo:7.0.6
6 | # If you want to expose these ports outside your dev PC,
7 | # remove the "127.0.0.1:" prefix
8 | ports:
9 | - 127.0.0.1:27017:27017
10 | # volumes:
11 | # - ~/volumes/jhipster/web/mongodb/:/data/db/
12 | healthcheck:
13 | test: ['CMD', 'echo', '''db.runCommand("ping").ok''', '|', 'mongo', 'localhost:27017/test', '--quiet']
14 | interval: 5s
15 | timeout: 5s
16 | retries: 10
17 |
--------------------------------------------------------------------------------
/src/main/docker/mongodb/MongoDB.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mongo:7.0.6
2 | ADD mongodb/scripts/init_replicaset.js init_replicaset.js
3 |
--------------------------------------------------------------------------------
/src/main/docker/mongodb/scripts/init_replicaset.js:
--------------------------------------------------------------------------------
1 | var status = rs.status();
2 | if (status.errmsg === 'no replset config has been received') {
3 | rs.initiate();
4 | }
5 | for (var i = 1; i <= param; i++) {
6 | if (i !== 1) rs.add(folder + '_web-mongodb-node_' + i + ':27018');
7 | }
8 | var cfg = rs.conf();
9 | cfg.members[0].host = folder + '_web-mongodb-node_1:27018';
10 | rs.reconfig(cfg);
11 |
--------------------------------------------------------------------------------
/src/main/docker/services.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | mongodb:
5 | extends:
6 | file: ./mongodb.yml
7 | service: mongodb
8 |
--------------------------------------------------------------------------------
/src/main/docker/sonar.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | sonar:
5 | container_name: sonarqube
6 | image: sonarqube:10.4.1-community
7 | # Forced authentication redirect for UI is turned off for out of the box experience while trying out SonarQube
8 | # For real use cases delete SONAR_FORCEAUTHENTICATION variable or set SONAR_FORCEAUTHENTICATION=true
9 | environment:
10 | - SONAR_FORCEAUTHENTICATION=false
11 | # If you want to expose these ports outside your dev PC,
12 | # remove the "127.0.0.1:" prefix
13 | ports:
14 | - 127.0.0.1:9001:9000
15 | - 127.0.0.1:9000:9000
16 |
--------------------------------------------------------------------------------
/src/main/docker/swagger-editor.yml:
--------------------------------------------------------------------------------
1 | # This configuration is intended for development purpose, it's **your** responsibility to harden it for production
2 | name: web
3 | services:
4 | swagger-editor:
5 | image: swaggerapi/swagger-editor:latest
6 | ports:
7 | - 127.0.0.1:7742:8080
8 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/ApplicationWebXml.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web;
2 |
3 | import org.springframework.boot.builder.SpringApplicationBuilder;
4 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
5 | import tech.jhipster.config.DefaultProfileUtil;
6 |
7 | /**
8 | * This is a helper Java class that provides an alternative to creating a {@code web.xml}.
9 | * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
10 | */
11 | public class ApplicationWebXml extends SpringBootServletInitializer {
12 |
13 | @Override
14 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
15 | // set a default to use when no profile is configured.
16 | DefaultProfileUtil.addDefaultProfile(application.application());
17 | return application.sources(WebApp.class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/GeneratedByJHipster.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web;
2 |
3 | import jakarta.annotation.Generated;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Generated(value = "JHipster", comments = "Generated by JHipster 8.3.0")
10 | @Retention(RetentionPolicy.SOURCE)
11 | @Target({ ElementType.TYPE })
12 | public @interface GeneratedByJHipster {
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/aop/logging/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Logging aspect.
3 | */
4 | package com.camenduru.web.aop.logging;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/ApplicationProperties.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | /**
6 | * Properties specific to Web.
7 | *
8 | * Properties are configured in the {@code application.yml} file.
9 | * See {@link tech.jhipster.config.JHipsterProperties} for a good example.
10 | */
11 | @ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
12 | public class ApplicationProperties {
13 | // jhipster-needle-application-properties-property
14 |
15 | // jhipster-needle-application-properties-property-getter
16 |
17 | // jhipster-needle-application-properties-property-class
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/Constants.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | /**
4 | * Application constants.
5 | */
6 | public final class Constants {
7 |
8 | // Regex for acceptable logins
9 | public static final String LOGIN_REGEX = "^(?>[a-zA-Z0-9!$&*+=?^_`{|}~.-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)|(?>[_.@A-Za-z0-9-]+)$";
10 |
11 | public static final String SYSTEM = "system";
12 | public static final String DEFAULT_LANGUAGE = "en";
13 |
14 | private Constants() {}
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/DateTimeFormatConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.format.FormatterRegistry;
5 | import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7 |
8 | /**
9 | * Configure the converters to use the ISO format for dates by default.
10 | */
11 | @Configuration
12 | public class DateTimeFormatConfiguration implements WebMvcConfigurer {
13 |
14 | @Override
15 | public void addFormatters(FormatterRegistry registry) {
16 | DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
17 | registrar.setUseIsoFormat(true);
18 | registrar.registerFormatters(registry);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/JacksonConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
4 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | public class JacksonConfiguration {
10 |
11 | /**
12 | * Support for Java date and time API.
13 | * @return the corresponding Jackson module.
14 | */
15 | @Bean
16 | public JavaTimeModule javaTimeModule() {
17 | return new JavaTimeModule();
18 | }
19 |
20 | @Bean
21 | public Jdk8Module jdk8TimeModule() {
22 | return new Jdk8Module();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/LocaleConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.LocaleResolver;
6 | import org.springframework.web.servlet.config.annotation.*;
7 | import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
8 | import tech.jhipster.config.locale.AngularCookieLocaleResolver;
9 |
10 | @Configuration
11 | public class LocaleConfiguration implements WebMvcConfigurer {
12 |
13 | @Bean
14 | public LocaleResolver localeResolver() {
15 | return new AngularCookieLocaleResolver("NG_TRANSLATE_LANG_KEY");
16 | }
17 |
18 | @Override
19 | public void addInterceptors(InterceptorRegistry registry) {
20 | LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
21 | localeChangeInterceptor.setParamName("language");
22 | registry.addInterceptor(localeChangeInterceptor);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/LoggingAspectConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import com.camenduru.web.aop.logging.LoggingAspect;
4 | import org.springframework.context.annotation.*;
5 | import org.springframework.core.env.Environment;
6 | import tech.jhipster.config.JHipsterConstants;
7 |
8 | @Configuration
9 | @EnableAspectJAutoProxy
10 | public class LoggingAspectConfiguration {
11 |
12 | @Bean
13 | @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
14 | public LoggingAspect loggingAspect(Environment env) {
15 | return new LoggingAspect(env);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/dbmigrations/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * This package file was generated by JHipster
3 | */
4 | package com.camenduru.web.config.dbmigrations;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/config/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Application configuration.
3 | */
4 | package com.camenduru.web.config;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/enumeration/JobSource.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain.enumeration;
2 |
3 | /**
4 | * The JobSource enumeration.
5 | */
6 | public enum JobSource {
7 | WEB,
8 | IOS,
9 | ANDROID,
10 | DISCORD,
11 | PAYPAL,
12 | PATREON,
13 | OTHER,
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/enumeration/JobStatus.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain.enumeration;
2 |
3 | /**
4 | * The JobStatus enumeration.
5 | */
6 | public enum JobStatus {
7 | POSITIVE,
8 | NEGATIVE,
9 | WAITING,
10 | WORKING,
11 | DONE,
12 | FAILED,
13 | CANCELED,
14 | EXPIRED,
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/enumeration/Membership.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain.enumeration;
2 |
3 | /**
4 | * The Membership enumeration.
5 | */
6 | public enum Membership {
7 | FREE,
8 | PAID,
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/enumeration/RedeemStatus.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain.enumeration;
2 |
3 | /**
4 | * The RedeemStatus enumeration.
5 | */
6 | public enum RedeemStatus {
7 | WAITING,
8 | USED,
9 | FAILED,
10 | CANCELED,
11 | EXPIRED,
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/enumeration/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * This package file was generated by JHipster
3 | */
4 | package com.camenduru.web.domain.enumeration;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/domain/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Domain objects.
3 | */
4 | package com.camenduru.web.domain;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/management/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Application management.
3 | */
4 | package com.camenduru.web.management;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Application root.
3 | */
4 | package com.camenduru.web;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/repository/AuthorityRepository.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.repository;
2 |
3 | import com.camenduru.web.domain.Authority;
4 | import org.springframework.data.mongodb.repository.MongoRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | /**
8 | * Spring Data MongoDB repository for the Authority entity.
9 | */
10 | @SuppressWarnings("unused")
11 | @Repository
12 | public interface AuthorityRepository extends MongoRepository {}
13 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/repository/RedeemRepository.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.repository;
2 |
3 | import com.camenduru.web.domain.Redeem;
4 | import java.util.List;
5 | import java.util.Optional;
6 | import org.springframework.data.domain.Page;
7 | import org.springframework.data.domain.Pageable;
8 | import org.springframework.data.mongodb.repository.MongoRepository;
9 | import org.springframework.data.mongodb.repository.Query;
10 | import org.springframework.stereotype.Repository;
11 |
12 | /**
13 | * Spring Data MongoDB repository for the Redeem entity.
14 | */
15 | @Repository
16 | public interface RedeemRepository extends MongoRepository {
17 | @Query("{}")
18 | Page findAllWithEagerRelationships(Pageable pageable);
19 |
20 | @Query("{}")
21 | List findAllWithEagerRelationships();
22 |
23 | @Query("{'id': ?0}")
24 | Optional findOneWithEagerRelationships(String id);
25 |
26 | @Query("{'code': ?0}")
27 | Redeem findOneWithCode(String code);
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/repository/TypeRepository.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.repository;
2 |
3 | import com.camenduru.web.domain.Type;
4 | import java.util.Optional;
5 | import org.springframework.data.mongodb.repository.MongoRepository;
6 | import org.springframework.data.mongodb.repository.Query;
7 | import org.springframework.stereotype.Repository;
8 |
9 | /**
10 | * Spring Data MongoDB repository for the Type entity.
11 | */
12 | @Repository
13 | public interface TypeRepository extends MongoRepository {
14 | @Query("{'type': ?0}")
15 | Optional findByType(String type);
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.repository;
2 |
3 | import com.camenduru.web.domain.User;
4 | import java.time.Instant;
5 | import java.util.List;
6 | import java.util.Optional;
7 | import org.springframework.cache.annotation.Cacheable;
8 | import org.springframework.data.domain.*;
9 | import org.springframework.data.mongodb.repository.MongoRepository;
10 | import org.springframework.stereotype.Repository;
11 |
12 | /**
13 | * Spring Data MongoDB repository for the {@link User} entity.
14 | */
15 | @Repository
16 | public interface UserRepository extends MongoRepository {
17 | String USERS_BY_LOGIN_CACHE = "usersByLogin";
18 |
19 | String USERS_BY_EMAIL_CACHE = "usersByEmail";
20 | Optional findOneByActivationKey(String activationKey);
21 | List findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(Instant dateTime);
22 | Optional findOneByResetKey(String resetKey);
23 |
24 | @Cacheable(cacheNames = USERS_BY_EMAIL_CACHE)
25 | Optional findOneByEmailIgnoreCase(String email);
26 |
27 | @Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)
28 | Optional findOneByLogin(String login);
29 |
30 | Page findAllByIdNotNullAndActivatedIsTrue(Pageable pageable);
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/repository/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Repository layer.
3 | */
4 | package com.camenduru.web.repository;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/security/AuthoritiesConstants.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.security;
2 |
3 | /**
4 | * Constants for Spring Security authorities.
5 | */
6 | public final class AuthoritiesConstants {
7 |
8 | public static final String ADMIN = "ROLE_ADMIN";
9 |
10 | public static final String USER = "ROLE_USER";
11 |
12 | public static final String ANONYMOUS = "ROLE_ANONYMOUS";
13 |
14 | private AuthoritiesConstants() {}
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/security/SpringSecurityAuditorAware.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.security;
2 |
3 | import com.camenduru.web.config.Constants;
4 | import java.util.Optional;
5 | import org.springframework.data.domain.AuditorAware;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * Implementation of {@link AuditorAware} based on Spring Security.
10 | */
11 | @Component
12 | public class SpringSecurityAuditorAware implements AuditorAware {
13 |
14 | @Override
15 | public Optional getCurrentAuditor() {
16 | return Optional.of(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/security/UserNotActivatedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.security;
2 |
3 | import org.springframework.security.core.AuthenticationException;
4 |
5 | /**
6 | * This exception is thrown in case of a not activated user trying to authenticate.
7 | */
8 | public class UserNotActivatedException extends AuthenticationException {
9 |
10 | private static final long serialVersionUID = 1L;
11 |
12 | public UserNotActivatedException(String message) {
13 | super(message);
14 | }
15 |
16 | public UserNotActivatedException(String message, Throwable t) {
17 | super(message, t);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/security/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Application security utilities.
3 | */
4 | package com.camenduru.web.security;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/EmailAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service;
2 |
3 | public class EmailAlreadyUsedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public EmailAlreadyUsedException() {
8 | super("Email is already in use!");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/EmailServiceNotAllowedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service;
2 |
3 | public class EmailServiceNotAllowedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public EmailServiceNotAllowedException() {
8 | super("Email service is not allowed!");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/InvalidPasswordException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service;
2 |
3 | public class InvalidPasswordException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public InvalidPasswordException() {
8 | super("Incorrect password");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/UsernameAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service;
2 |
3 | public class UsernameAlreadyUsedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public UsernameAlreadyUsedException() {
8 | super("Login name already used!");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/chat/ChatRequestBody.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.chat;
2 |
3 | public class ChatRequestBody {
4 |
5 | private ChatRequestMessage[] messages;
6 | private String model;
7 | private Boolean stream;
8 |
9 | public ChatRequestMessage[] getMessages() {
10 | return this.messages;
11 | }
12 |
13 | public String getModel() {
14 | return this.model;
15 | }
16 |
17 | public Boolean getStream() {
18 | return this.stream;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/chat/ChatRequestMessage.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.chat;
2 |
3 | public class ChatRequestMessage {
4 |
5 | private String role;
6 | private String text;
7 |
8 | public String getRole() {
9 | return this.role;
10 | }
11 |
12 | public String getText() {
13 | return this.text;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/chat/ChatTextRespose.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.chat;
2 |
3 | public class ChatTextRespose {
4 |
5 | private String text;
6 |
7 | public ChatTextRespose(String text) {
8 | if (text != null) {
9 | this.text = text;
10 | }
11 | }
12 |
13 | public String getText() {
14 | return text;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/dto/NotifyDTO.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.dto;
2 |
3 | public class NotifyDTO {
4 |
5 | private String jobId;
6 | private String result;
7 |
8 | public String getJobId() {
9 | return jobId;
10 | }
11 |
12 | public void setJobid(String jobId) {
13 | this.jobId = jobId;
14 | }
15 |
16 | public String getResult() {
17 | return result;
18 | }
19 |
20 | public void setResult(String result) {
21 | this.result = result;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/dto/PasswordChangeDTO.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.dto;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * A DTO representing a password change required data - current and new password.
7 | */
8 | public class PasswordChangeDTO implements Serializable {
9 |
10 | private static final long serialVersionUID = 1L;
11 |
12 | private String currentPassword;
13 | private String newPassword;
14 |
15 | public PasswordChangeDTO() {
16 | // Empty constructor needed for Jackson.
17 | }
18 |
19 | public PasswordChangeDTO(String currentPassword, String newPassword) {
20 | this.currentPassword = currentPassword;
21 | this.newPassword = newPassword;
22 | }
23 |
24 | public String getCurrentPassword() {
25 | return currentPassword;
26 | }
27 |
28 | public void setCurrentPassword(String currentPassword) {
29 | this.currentPassword = currentPassword;
30 | }
31 |
32 | public String getNewPassword() {
33 | return newPassword;
34 | }
35 |
36 | public void setNewPassword(String newPassword) {
37 | this.newPassword = newPassword;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/dto/UserDTO.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.service.dto;
2 |
3 | import com.camenduru.web.domain.User;
4 | import java.io.Serializable;
5 |
6 | /**
7 | * A DTO representing a user, with only the public attributes.
8 | */
9 | public class UserDTO implements Serializable {
10 |
11 | private static final long serialVersionUID = 1L;
12 |
13 | private String id;
14 |
15 | private String login;
16 |
17 | public UserDTO() {
18 | // Empty constructor needed for Jackson.
19 | }
20 |
21 | public UserDTO(User user) {
22 | this.id = user.getId();
23 | // Customize it here if you need, or not, firstName/lastName/etc
24 | this.login = user.getLogin();
25 | }
26 |
27 | public String getId() {
28 | return id;
29 | }
30 |
31 | public void setId(String id) {
32 | this.id = id;
33 | }
34 |
35 | public String getLogin() {
36 | return login;
37 | }
38 |
39 | public void setLogin(String login) {
40 | this.login = login;
41 | }
42 |
43 | // prettier-ignore
44 | @Override
45 | public String toString() {
46 | return "UserDTO{" +
47 | "id='" + id + '\'' +
48 | ", login='" + login + '\'' +
49 | "}";
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/dto/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Data transfer objects for rest mapping.
3 | */
4 | package com.camenduru.web.service.dto;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/mapper/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Data transfer objects mappers.
3 | */
4 | package com.camenduru.web.service.mapper;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/service/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Service layer.
3 | */
4 | package com.camenduru.web.service;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/filter/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Request chain filters.
3 | */
4 | package com.camenduru.web.web.filter;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/EmailAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | @SuppressWarnings("java:S110") // Inheritance tree of classes should not be too deep
4 | public class EmailAlreadyUsedException extends BadRequestAlertException {
5 |
6 | private static final long serialVersionUID = 1L;
7 |
8 | public EmailAlreadyUsedException() {
9 | super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email is already in use!", "userManagement", "emailexists");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/EmailServiceNotAllowedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | @SuppressWarnings("java:S110") // Inheritance tree of classes should not be too deep
4 | public class EmailServiceNotAllowedException extends BadRequestAlertException {
5 |
6 | private static final long serialVersionUID = 1L;
7 |
8 | public EmailServiceNotAllowedException() {
9 | super(ErrorConstants.EMAIL_SERVICE_NOT_ALLOWED_TYPE, "Email service is not allowed!", "userManagement", "emailservicenotallowed");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/ErrorConstants.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | import java.net.URI;
4 |
5 | public final class ErrorConstants {
6 |
7 | public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
8 | public static final String ERR_VALIDATION = "error.validation";
9 | public static final String PROBLEM_BASE_URL = "http://localhost:8080/problem";
10 | public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message");
11 | public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation");
12 | public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password");
13 | public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used");
14 | public static final URI EMAIL_SERVICE_NOT_ALLOWED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-service-not-allowed");
15 | public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used");
16 |
17 | private ErrorConstants() {}
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/FieldErrorVM.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | import java.io.Serializable;
4 |
5 | public class FieldErrorVM implements Serializable {
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | private final String objectName;
10 |
11 | private final String field;
12 |
13 | private final String message;
14 |
15 | public FieldErrorVM(String dto, String field, String message) {
16 | this.objectName = dto;
17 | this.field = field;
18 | this.message = message;
19 | }
20 |
21 | public String getObjectName() {
22 | return objectName;
23 | }
24 |
25 | public String getField() {
26 | return field;
27 | }
28 |
29 | public String getMessage() {
30 | return message;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/InvalidPasswordException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | import org.springframework.http.HttpStatus;
4 | import org.springframework.web.ErrorResponseException;
5 | import tech.jhipster.web.rest.errors.ProblemDetailWithCause.ProblemDetailWithCauseBuilder;
6 |
7 | @SuppressWarnings("java:S110") // Inheritance tree of classes should not be too deep
8 | public class InvalidPasswordException extends ErrorResponseException {
9 |
10 | private static final long serialVersionUID = 1L;
11 |
12 | public InvalidPasswordException() {
13 | super(
14 | HttpStatus.BAD_REQUEST,
15 | ProblemDetailWithCauseBuilder.instance()
16 | .withStatus(HttpStatus.BAD_REQUEST.value())
17 | .withType(ErrorConstants.INVALID_PASSWORD_TYPE)
18 | .withTitle("Incorrect password")
19 | .build(),
20 | null
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/LoginAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.errors;
2 |
3 | @SuppressWarnings("java:S110") // Inheritance tree of classes should not be too deep
4 | public class LoginAlreadyUsedException extends BadRequestAlertException {
5 |
6 | private static final long serialVersionUID = 1L;
7 |
8 | public LoginAlreadyUsedException() {
9 | super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login name already used!", "userManagement", "userexists");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/errors/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Rest layer error handling.
3 | */
4 | package com.camenduru.web.web.rest.errors;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Rest layer.
3 | */
4 | package com.camenduru.web.web.rest;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/vm/KeyAndPasswordVM.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.vm;
2 |
3 | /**
4 | * View Model object for storing the user's key and password.
5 | */
6 | public class KeyAndPasswordVM {
7 |
8 | private String key;
9 |
10 | private String newPassword;
11 |
12 | public String getKey() {
13 | return key;
14 | }
15 |
16 | public void setKey(String key) {
17 | this.key = key;
18 | }
19 |
20 | public String getNewPassword() {
21 | return newPassword;
22 | }
23 |
24 | public void setNewPassword(String newPassword) {
25 | this.newPassword = newPassword;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/vm/ManagedUserVM.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest.vm;
2 |
3 | import com.camenduru.web.service.dto.AdminUserDTO;
4 | import jakarta.validation.constraints.Size;
5 |
6 | /**
7 | * View Model extending the AdminUserDTO, which is meant to be used in the user management UI.
8 | */
9 | public class ManagedUserVM extends AdminUserDTO {
10 |
11 | public static final int PASSWORD_MIN_LENGTH = 4;
12 |
13 | public static final int PASSWORD_MAX_LENGTH = 100;
14 |
15 | @Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH)
16 | private String password;
17 |
18 | public ManagedUserVM() {
19 | // Empty constructor needed for Jackson.
20 | }
21 |
22 | public String getPassword() {
23 | return password;
24 | }
25 |
26 | public void setPassword(String password) {
27 | this.password = password;
28 | }
29 |
30 | // prettier-ignore
31 | @Override
32 | public String toString() {
33 | return "ManagedUserVM{" + super.toString() + "} ";
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/rest/vm/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Rest layer visual models.
3 | */
4 | package com.camenduru.web.web.rest.vm;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/websocket/dto/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * This package file was generated by JHipster
3 | */
4 | package com.camenduru.web.web.websocket.dto;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/camenduru/web/web/websocket/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * This package file was generated by JHipster
3 | */
4 | package com.camenduru.web.web.websocket;
5 |
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 |
2 | ${AnsiColor.GREEN} ██╗${AnsiColor.RED} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗
3 | ${AnsiColor.GREEN} ██║${AnsiColor.RED} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗
4 | ${AnsiColor.GREEN} ██║${AnsiColor.RED} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝
5 | ${AnsiColor.GREEN}██╗ ██║${AnsiColor.RED} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║
6 | ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.RED} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗
7 | ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.RED} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝
8 |
9 | ${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} :: Startup profile(s) ${spring.profiles.active} ::
10 | :: https://www.jhipster.tech ::${AnsiColor.DEFAULT}
11 |
--------------------------------------------------------------------------------
/src/main/resources/config/application-tls.yml:
--------------------------------------------------------------------------------
1 | # ===================================================================
2 | # Activate this profile to enable TLS and HTTP/2.
3 | #
4 | # JHipster has generated a self-signed certificate, which will be used to encrypt traffic.
5 | # As your browser will not understand this certificate, you will need to import it.
6 | #
7 | # Another (easiest) solution with Chrome is to enable the "allow-insecure-localhost" flag
8 | # at chrome://flags/#allow-insecure-localhost
9 | # ===================================================================
10 | server:
11 | ssl:
12 | key-store: classpath:config/tls/keystore.p12
13 | key-store-password: password
14 | key-store-type: PKCS12
15 | key-alias: selfsigned
16 | ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
17 | enabled-protocols: TLSv1.2
18 | http2:
19 | enabled: true
20 |
--------------------------------------------------------------------------------
/src/main/resources/config/tls/keystore.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/resources/config/tls/keystore.p12
--------------------------------------------------------------------------------
/src/main/resources/i18n/messages.properties:
--------------------------------------------------------------------------------
1 | # Error page
2 | error.title=Your request cannot be processed
3 | error.subtitle=Sorry, an error has occurred.
4 | error.status=Status:
5 | error.message=Message:
6 |
7 | # Activation email
8 | email.activation.title=Tost account activation
9 | email.activation.greeting=Dear {0}
10 | email.activation.text1=Your Tost account has been created, please click on the URL below to activate it:
11 | email.activation.text2=Regards,
12 | email.signature=Tost Team.
13 |
14 | # Creation email
15 | email.creation.text1=Your Tost account has been created, please click on the URL below to access it:
16 |
17 | # Reset email
18 | email.reset.title=Tost password reset
19 | email.reset.greeting=Dear {0}
20 | email.reset.text1=For your Tost account a password reset was requested, please click on the URL below to reset it:
21 | email.reset.text2=Regards,
22 |
--------------------------------------------------------------------------------
/src/main/resources/i18n/messages_en.properties:
--------------------------------------------------------------------------------
1 | # Error page
2 | error.title=Your request cannot be processed
3 | error.subtitle=Sorry, an error has occurred.
4 | error.status=Status:
5 | error.message=Message:
6 |
7 | # Activation email
8 | email.activation.title=Tost account activation
9 | email.activation.greeting=Dear {0}
10 | email.activation.text1=Your Tost account has been created, please click on the URL below to activate it:
11 | email.activation.text2=Regards,
12 | email.signature=Tost Team.
13 |
14 | # Creation email
15 | email.creation.text1=Your Tost account has been created, please click on the URL below to access it:
16 |
17 | # Reset email
18 | email.reset.title=Tost password reset
19 | email.reset.greeting=Dear {0}
20 | email.reset.text1=For your Tost account a password reset was requested, please click on the URL below to reset it:
21 | email.reset.text2=Regards,
22 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/activationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster activation
5 |
6 |
7 |
8 |
9 | Dear
10 | Your JHipster account has been created, please click on the URL below to activate it:
11 |
12 | Activation link
13 |
14 |
15 | Regards,
16 |
17 | JHipster.
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/creationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster creation
5 |
6 |
7 |
8 |
9 | Dear
10 | Your JHipster account has been created, please click on the URL below to access it:
11 |
12 | Login link
13 |
14 |
15 | Regards,
16 |
17 | JHipster.
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/passwordResetEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster password reset
5 |
6 |
7 |
8 |
9 | Dear
10 |
11 | For your JHipster account a password reset was requested, please click on the URL below to reset it:
12 |
13 |
14 | Login link
15 |
16 |
17 | Regards,
18 |
19 | JHipster.
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | html
10 | text/html;charset=utf-8
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/account.route.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import activateRoute from './activate/activate.route';
4 | import passwordRoute from './password/password.route';
5 | import passwordResetFinishRoute from './password-reset/finish/password-reset-finish.route';
6 | import passwordResetInitRoute from './password-reset/init/password-reset-init.route';
7 | import registerRoute from './register/register.route';
8 | import settingsRoute from './settings/settings.route';
9 |
10 | const accountRoutes: Routes = [
11 | activateRoute,
12 | passwordRoute,
13 | passwordResetFinishRoute,
14 | passwordResetInitRoute,
15 | registerRoute,
16 | settingsRoute,
17 | ];
18 |
19 | export default accountRoutes;
20 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/activate/activate.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Activation
5 | @if (success()) {
6 |
7 |
Your user account has been activated. Please
8 |
sign in.
9 |
10 | }
11 | @if (error()) {
12 |
13 | Your user could not be activated. Please use the registration form to sign up.
14 |
15 | }
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/activate/activate.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject, OnInit, signal } from '@angular/core';
2 | import { ActivatedRoute, RouterModule } from '@angular/router';
3 | import { mergeMap } from 'rxjs/operators';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ActivateService } from './activate.service';
7 |
8 | @Component({
9 | standalone: true,
10 | selector: 'jhi-activate',
11 | imports: [SharedModule, RouterModule],
12 | templateUrl: './activate.component.html',
13 | })
14 | export default class ActivateComponent implements OnInit {
15 | error = signal(false);
16 | success = signal(false);
17 |
18 | private activateService = inject(ActivateService);
19 | private route = inject(ActivatedRoute);
20 |
21 | ngOnInit(): void {
22 | this.route.queryParams.pipe(mergeMap(params => this.activateService.get(params.key))).subscribe({
23 | next: () => this.success.set(true),
24 | error: () => this.error.set(true),
25 | });
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/activate/activate.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import ActivateComponent from './activate.component';
4 |
5 | const activateRoute: Route = {
6 | path: 'activate',
7 | component: ActivateComponent,
8 | title: 'activate.title',
9 | };
10 |
11 | export default activateRoute;
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/activate/activate.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient, HttpParams } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 |
7 | @Injectable({ providedIn: 'root' })
8 | export class ActivateService {
9 | private http = inject(HttpClient);
10 | private applicationConfigService = inject(ApplicationConfigService);
11 |
12 | get(key: string): Observable<{}> {
13 | return this.http.get(this.applicationConfigService.getEndpointFor('api/activate'), {
14 | params: new HttpParams().set('key', key),
15 | });
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import PasswordResetFinishComponent from './password-reset-finish.component';
4 |
5 | const passwordResetFinishRoute: Route = {
6 | path: 'reset/finish',
7 | component: PasswordResetFinishComponent,
8 | title: 'global.menu.account.password',
9 | };
10 |
11 | export default passwordResetFinishRoute;
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 |
7 | @Injectable({ providedIn: 'root' })
8 | export class PasswordResetFinishService {
9 | private http = inject(HttpClient);
10 | private applicationConfigService = inject(ApplicationConfigService);
11 |
12 | save(key: string, newPassword: string): Observable<{}> {
13 | return this.http.post(this.applicationConfigService.getEndpointFor('api/account/reset-password/finish'), { key, newPassword });
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import PasswordResetInitComponent from './password-reset-init.component';
4 |
5 | const passwordResetInitRoute: Route = {
6 | path: 'reset/request',
7 | component: PasswordResetInitComponent,
8 | title: 'global.menu.account.password',
9 | };
10 |
11 | export default passwordResetInitRoute;
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 |
7 | @Injectable({ providedIn: 'root' })
8 | export class PasswordResetInitService {
9 | private http = inject(HttpClient);
10 | private applicationConfigService = inject(ApplicationConfigService);
11 |
12 | save(mail: string): Observable<{}> {
13 | return this.http.post(this.applicationConfigService.getEndpointFor('api/account/reset-password/init'), mail);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password/password-strength-bar/password-strength-bar.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Password strength:
3 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password/password-strength-bar/password-strength-bar.component.scss:
--------------------------------------------------------------------------------
1 | /* ==========================================================================
2 | start Password strength bar style
3 | ========================================================================== */
4 | ul#strength {
5 | display: inline;
6 | list-style: none;
7 | margin: 0;
8 | margin-left: 15px;
9 | padding: 0;
10 | vertical-align: 2px;
11 | }
12 |
13 | .point {
14 | background: #ddd;
15 | border-radius: 2px;
16 | display: inline-block;
17 | height: 5px;
18 | margin-right: 1px;
19 | width: 20px;
20 | &:last-child {
21 | margin: 0 !important;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password/password.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import PasswordComponent from './password.component';
5 |
6 | const passwordRoute: Route = {
7 | path: 'password',
8 | component: PasswordComponent,
9 | title: 'global.menu.account.password',
10 | canActivate: [UserRouteAccessService],
11 | };
12 |
13 | export default passwordRoute;
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/password/password.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 |
7 | @Injectable({ providedIn: 'root' })
8 | export class PasswordService {
9 | private http = inject(HttpClient);
10 | private applicationConfigService = inject(ApplicationConfigService);
11 |
12 | save(newPassword: string, currentPassword: string): Observable<{}> {
13 | return this.http.post(this.applicationConfigService.getEndpointFor('api/account/change-password'), { currentPassword, newPassword });
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/register/register.model.ts:
--------------------------------------------------------------------------------
1 | export class Registration {
2 | constructor(
3 | public login: string,
4 | public email: string,
5 | public password: string,
6 | public langKey: string,
7 | ) {}
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/register/register.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import RegisterComponent from './register.component';
4 |
5 | const registerRoute: Route = {
6 | path: 'register',
7 | component: RegisterComponent,
8 | title: 'register.title',
9 | };
10 |
11 | export default registerRoute;
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/register/register.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 | import { Registration } from './register.model';
7 |
8 | @Injectable({ providedIn: 'root' })
9 | export class RegisterService {
10 | private http = inject(HttpClient);
11 | private applicationConfigService = inject(ApplicationConfigService);
12 |
13 | save(registration: Registration): Observable<{}> {
14 | return this.http.post(this.applicationConfigService.getEndpointFor('api/register'), registration);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/webapp/app/account/settings/settings.route.ts:
--------------------------------------------------------------------------------
1 | import { Route } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import SettingsComponent from './settings.component';
5 |
6 | const settingsRoute: Route = {
7 | path: 'settings',
8 | component: SettingsComponent,
9 | title: 'global.menu.account.settings',
10 | canActivate: [UserRouteAccessService],
11 | };
12 |
13 | export default settingsRoute;
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/configuration/configuration.model.ts:
--------------------------------------------------------------------------------
1 | export interface ConfigProps {
2 | contexts: Contexts;
3 | }
4 |
5 | export interface Contexts {
6 | [key: string]: Context;
7 | }
8 |
9 | export interface Context {
10 | beans: Beans;
11 | parentId?: any;
12 | }
13 |
14 | export interface Beans {
15 | [key: string]: Bean;
16 | }
17 |
18 | export interface Bean {
19 | prefix: string;
20 | properties: any;
21 | }
22 |
23 | export interface Env {
24 | activeProfiles?: string[];
25 | propertySources: PropertySource[];
26 | }
27 |
28 | export interface PropertySource {
29 | name: string;
30 | properties: Properties;
31 | }
32 |
33 | export interface Properties {
34 | [key: string]: Property;
35 | }
36 |
37 | export interface Property {
38 | value: string;
39 | origin?: string;
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/docs/docs.component.html:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/docs/docs.component.scss:
--------------------------------------------------------------------------------
1 | @import 'bootstrap/scss/functions';
2 | @import 'bootswatch/dist/darkly/variables';
3 | @import 'bootstrap/scss/variables';
4 |
5 | iframe {
6 | background: white;
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/docs/docs.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | standalone: true,
5 | selector: 'jhi-docs',
6 | templateUrl: './docs.component.html',
7 | styleUrl: './docs.component.scss',
8 | })
9 | export default class DocsComponent {}
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/health/health.model.ts:
--------------------------------------------------------------------------------
1 | export type HealthStatus = 'UP' | 'DOWN' | 'UNKNOWN' | 'OUT_OF_SERVICE';
2 |
3 | export type HealthKey = 'diskSpace' | 'mail' | 'ping' | 'livenessState' | 'readinessState' | 'mongo';
4 |
5 | export interface Health {
6 | status: HealthStatus;
7 | components: {
8 | [key in HealthKey]?: HealthDetails;
9 | };
10 | }
11 |
12 | export interface HealthDetails {
13 | status: HealthStatus;
14 | details?: { [key: string]: unknown };
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/health/health.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 | import { Health } from './health.model';
7 |
8 | @Injectable({ providedIn: 'root' })
9 | export class HealthService {
10 | private http = inject(HttpClient);
11 | private applicationConfigService = inject(ApplicationConfigService);
12 |
13 | checkHealth(): Observable {
14 | return this.http.get(this.applicationConfigService.getEndpointFor('management/health'));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/health/modal/health-modal.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
3 |
4 | import SharedModule from 'app/shared/shared.module';
5 | import { HealthKey, HealthDetails } from '../health.model';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-health-modal',
10 | templateUrl: './health-modal.component.html',
11 | imports: [SharedModule],
12 | })
13 | export default class HealthModalComponent {
14 | health?: { key: HealthKey; value: HealthDetails };
15 |
16 | private activeModal = inject(NgbActiveModal);
17 |
18 | readableValue(value: any): string {
19 | if (this.health?.key === 'diskSpace') {
20 | // Should display storage space in an human readable unit
21 | const val = value / 1073741824;
22 | if (val > 1) {
23 | return `${val.toFixed(2)} GB`;
24 | }
25 | return `${(value / 1048576).toFixed(2)} MB`;
26 | }
27 |
28 | if (typeof value === 'object') {
29 | return JSON.stringify(value);
30 | }
31 | return String(value);
32 | }
33 |
34 | dismiss(): void {
35 | this.activeModal.dismiss();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/logs/log.model.ts:
--------------------------------------------------------------------------------
1 | export type Level = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'OFF';
2 |
3 | export interface Logger {
4 | configuredLevel: Level | null;
5 | effectiveLevel: Level;
6 | }
7 |
8 | export interface LoggersResponse {
9 | levels: Level[];
10 | loggers: { [key: string]: Logger };
11 | }
12 |
13 | export class Log {
14 | constructor(
15 | public name: string,
16 | public level: Level,
17 | ) {}
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/logs/logs.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
3 |
4 | import { LogsService } from './logs.service';
5 |
6 | describe('Logs Service', () => {
7 | let service: LogsService;
8 | let httpMock: HttpTestingController;
9 |
10 | beforeEach(() => {
11 | TestBed.configureTestingModule({
12 | imports: [HttpClientTestingModule],
13 | });
14 |
15 | service = TestBed.inject(LogsService);
16 | httpMock = TestBed.inject(HttpTestingController);
17 | });
18 |
19 | afterEach(() => {
20 | httpMock.verify();
21 | });
22 |
23 | describe('Service methods', () => {
24 | it('should change log level', () => {
25 | service.changeLevel('main', 'ERROR').subscribe();
26 |
27 | const req = httpMock.expectOne({ method: 'POST' });
28 | expect(req.request.body).toEqual({ configuredLevel: 'ERROR' });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/logs/logs.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 | import { LoggersResponse, Level } from './log.model';
7 |
8 | @Injectable({ providedIn: 'root' })
9 | export class LogsService {
10 | private http = inject(HttpClient);
11 | private applicationConfigService = inject(ApplicationConfigService);
12 |
13 | changeLevel(name: string, configuredLevel: Level): Observable<{}> {
14 | return this.http.post(this.applicationConfigService.getEndpointFor(`management/loggers/${name}`), { configuredLevel });
15 | }
16 |
17 | findAll(): Observable {
18 | return this.http.get(this.applicationConfigService.getEndpointFor('management/loggers'));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.html:
--------------------------------------------------------------------------------
1 | Memory
2 |
3 | @if (!updating() && jvmMemoryMetrics()) {
4 |
5 | @for (entry of jvmMemoryMetrics() | keyvalue; track $index) {
6 |
7 | @if (entry.value.max !== -1) {
8 |
9 | {{ entry.key }}
10 | ({{ entry.value.used / 1048576 | number: '1.0-0' }}M / {{ entry.value.max / 1048576 | number: '1.0-0' }}M)
11 |
12 |
13 |
Committed : {{ entry.value.committed / 1048576 | number: '1.0-0' }}M
14 |
15 | {{ (entry.value.used * 100) / entry.value.max | number: '1.0-0' }}%
16 |
17 | } @else {
18 |
{{ entry.key }} {{ entry.value.used / 1048576 | number: '1.0-0' }}M
21 | }
22 |
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { JvmMetrics } from 'app/admin/metrics/metrics.model';
5 |
6 | @Component({
7 | standalone: true,
8 | selector: 'jhi-jvm-memory',
9 | templateUrl: './jvm-memory.component.html',
10 | imports: [SharedModule],
11 | })
12 | export class JvmMemoryComponent {
13 | /**
14 | * object containing all jvm memory metrics
15 | */
16 | jvmMemoryMetrics = input<{ [key: string]: JvmMetrics }>();
17 |
18 | /**
19 | * boolean field saying if the metrics are in the process of being updated
20 | */
21 | updating = input();
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { CacheMetrics } from 'app/admin/metrics/metrics.model';
5 | import { filterNaN } from 'app/core/util/operators';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-metrics-cache',
10 | templateUrl: './metrics-cache.component.html',
11 | changeDetection: ChangeDetectionStrategy.OnPush,
12 | imports: [SharedModule],
13 | })
14 | export class MetricsCacheComponent {
15 | /**
16 | * object containing all cache related metrics
17 | */
18 | cacheMetrics = input<{ [key: string]: CacheMetrics }>();
19 |
20 | /**
21 | * boolean field saying if the metrics are in the process of being updated
22 | */
23 | updating = input();
24 |
25 | filterNaN = (n: number): number => filterNaN(n);
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { Databases } from 'app/admin/metrics/metrics.model';
5 | import { filterNaN } from 'app/core/util/operators';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-metrics-datasource',
10 | templateUrl: './metrics-datasource.component.html',
11 | changeDetection: ChangeDetectionStrategy.OnPush,
12 | imports: [SharedModule],
13 | })
14 | export class MetricsDatasourceComponent {
15 | /**
16 | * object containing all datasource related metrics
17 | */
18 | datasourceMetrics = input();
19 |
20 | /**
21 | * boolean field saying if the metrics are in the process of being updated
22 | */
23 | updating = input();
24 |
25 | filterNaN = (n: number): number => filterNaN(n);
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.html:
--------------------------------------------------------------------------------
1 | Endpoints requests (time in millisecond)
2 |
3 | @if (!updating() && endpointsRequestsMetrics()) {
4 |
5 |
6 |
7 |
8 | Method |
9 | Endpoint url |
10 | Count |
11 | Mean |
12 |
13 |
14 |
15 | @for (entry of endpointsRequestsMetrics() | keyvalue; track entry.key) {
16 | @for (method of entry.value | keyvalue; track method.key) {
17 |
18 | {{ method.key }} |
19 | {{ entry.key }} |
20 | {{ method.value!.count }} |
21 | {{ method.value!.mean | number: '1.0-3' }} |
22 |
23 | }
24 | }
25 |
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { Services } from 'app/admin/metrics/metrics.model';
5 |
6 | @Component({
7 | standalone: true,
8 | selector: 'jhi-metrics-endpoints-requests',
9 | templateUrl: './metrics-endpoints-requests.component.html',
10 | imports: [SharedModule],
11 | })
12 | export class MetricsEndpointsRequestsComponent {
13 | /**
14 | * object containing service related metrics
15 | */
16 | endpointsRequestsMetrics = input();
17 |
18 | /**
19 | * boolean field saying if the metrics are in the process of being updated
20 | */
21 | updating = input();
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { GarbageCollector } from 'app/admin/metrics/metrics.model';
5 |
6 | @Component({
7 | standalone: true,
8 | selector: 'jhi-metrics-garbagecollector',
9 | templateUrl: './metrics-garbagecollector.component.html',
10 | imports: [SharedModule],
11 | })
12 | export class MetricsGarbageCollectorComponent {
13 | /**
14 | * object containing garbage collector related metrics
15 | */
16 | garbageCollectorMetrics = input();
17 |
18 | /**
19 | * boolean field saying if the metrics are in the process of being updated
20 | */
21 | updating = input();
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.ts:
--------------------------------------------------------------------------------
1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core';
2 |
3 | import SharedModule from 'app/shared/shared.module';
4 | import { HttpServerRequests } from 'app/admin/metrics/metrics.model';
5 | import { filterNaN } from 'app/core/util/operators';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-metrics-request',
10 | templateUrl: './metrics-request.component.html',
11 | changeDetection: ChangeDetectionStrategy.OnPush,
12 | imports: [SharedModule],
13 | })
14 | export class MetricsRequestComponent {
15 | /**
16 | * object containing http request related metrics
17 | */
18 | requestMetrics = input();
19 |
20 | /**
21 | * boolean field saying if the metrics are in the process of being updated
22 | */
23 | updating = input();
24 |
25 | filterNaN = (n: number): number => filterNaN(n);
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/metrics/metrics.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { ApplicationConfigService } from 'app/core/config/application-config.service';
6 | import { Metrics, ThreadDump } from './metrics.model';
7 |
8 | @Injectable({ providedIn: 'root' })
9 | export class MetricsService {
10 | private http = inject(HttpClient);
11 | private applicationConfigService = inject(ApplicationConfigService);
12 |
13 | getMetrics(): Observable {
14 | return this.http.get(this.applicationConfigService.getEndpointFor('management/jhimetrics'));
15 | }
16 |
17 | threadDump(): Observable {
18 | return this.http.get(this.applicationConfigService.getEndpointFor('management/threaddump'));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/tracker/tracker.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Real-time user activities
3 |
4 |
5 |
6 |
7 |
8 | User |
9 | IP Address |
10 | Current page |
11 | Time |
12 |
13 |
14 |
15 | @for (activity of activities; track $index) {
16 |
17 | {{ activity.userLogin }} |
18 | {{ activity.ipAddress }} |
19 | {{ activity.page }} |
20 | {{ activity.time | date: 'yyyy-MM-dd HH:mm:ss' }} |
21 |
22 | }
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/user-management/delete/user-management-delete-dialog.component.html:
--------------------------------------------------------------------------------
1 | @if (user) {
2 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/user-management/delete/user-management-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { User } from '../user-management.model';
7 | import { UserManagementService } from '../service/user-management.service';
8 |
9 | @Component({
10 | standalone: true,
11 | selector: 'jhi-user-mgmt-delete-dialog',
12 | templateUrl: './user-management-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export default class UserManagementDeleteDialogComponent {
16 | user?: User;
17 |
18 | private userService = inject(UserManagementService);
19 | private activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(login: string): void {
26 | this.userService.delete(login).subscribe(() => {
27 | this.activeModal.close('deleted');
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/user-management/detail/user-management-detail.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 | import SharedModule from 'app/shared/shared.module';
4 |
5 | import { User } from '../user-management.model';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-user-mgmt-detail',
10 | templateUrl: './user-management-detail.component.html',
11 | imports: [RouterModule, SharedModule],
12 | })
13 | export default class UserManagementDetailComponent {
14 | user = input(null);
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/admin/user-management/user-management.model.ts:
--------------------------------------------------------------------------------
1 | export interface IUser {
2 | id: string | null;
3 | login?: string;
4 | firstName?: string | null;
5 | lastName?: string | null;
6 | email?: string;
7 | activated?: boolean;
8 | langKey?: string;
9 | authorities?: string[];
10 | createdBy?: string;
11 | createdDate?: Date;
12 | lastModifiedBy?: string;
13 | lastModifiedDate?: Date;
14 | }
15 |
16 | export class User implements IUser {
17 | constructor(
18 | public id: string | null,
19 | public login?: string,
20 | public firstName?: string | null,
21 | public lastName?: string | null,
22 | public email?: string,
23 | public activated?: boolean,
24 | public langKey?: string,
25 | public authorities?: string[],
26 | public createdBy?: string,
27 | public createdDate?: Date,
28 | public lastModifiedBy?: string,
29 | public lastModifiedDate?: Date,
30 | ) {}
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/webapp/app/app-page-title-strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, inject } from '@angular/core';
2 | import { RouterStateSnapshot, TitleStrategy } from '@angular/router';
3 | import { TranslateService } from '@ngx-translate/core';
4 |
5 | @Injectable()
6 | export class AppPageTitleStrategy extends TitleStrategy {
7 | private translateService = inject(TranslateService);
8 |
9 | override updateTitle(routerState: RouterStateSnapshot): void {
10 | let pageTitle = this.buildTitle(routerState);
11 | if (!pageTitle) {
12 | pageTitle = 'global.title';
13 | }
14 | this.translateService.get(pageTitle).subscribe(title => {
15 | document.title = title;
16 | });
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/app.constants.ts:
--------------------------------------------------------------------------------
1 | // These constants are injected via webpack DefinePlugin variables.
2 | // You can add more variables in webpack.common.js or in profile specific webpack..js files.
3 | // If you change the values in the webpack config files, you need to re run webpack to update the application
4 |
5 | declare const __DEBUG_INFO_ENABLED__: boolean;
6 | declare const __VERSION__: string;
7 |
8 | export const VERSION = __VERSION__;
9 | export const DEBUG_INFO_ENABLED = __DEBUG_INFO_ENABLED__;
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import { Authority } from 'app/config/authority.constants';
4 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
5 | import { errorRoute } from './layouts/error/error.route';
6 |
7 | import HomeComponent from './home/home.component';
8 | import NavbarComponent from './layouts/navbar/navbar.component';
9 | import LoginComponent from './login/login.component';
10 |
11 | const routes: Routes = [
12 | {
13 | path: '',
14 | component: HomeComponent,
15 | title: 'home.title',
16 | },
17 | {
18 | path: '',
19 | component: NavbarComponent,
20 | outlet: 'navbar',
21 | },
22 | {
23 | path: 'admin',
24 | data: {
25 | authorities: [Authority.ADMIN],
26 | },
27 | canActivate: [UserRouteAccessService],
28 | loadChildren: () => import('./admin/admin.routes'),
29 | },
30 | {
31 | path: 'account',
32 | loadChildren: () => import('./account/account.route'),
33 | },
34 | {
35 | path: 'login',
36 | component: LoginComponent,
37 | title: 'login.title',
38 | },
39 | {
40 | path: '',
41 | loadChildren: () => import(`./entities/entity.routes`),
42 | },
43 | ...errorRoute,
44 | ];
45 |
46 | export default routes;
47 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/authority.constants.ts:
--------------------------------------------------------------------------------
1 | export enum Authority {
2 | ADMIN = 'ROLE_ADMIN',
3 | USER = 'ROLE_USER',
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/datepicker-adapter.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Angular bootstrap Date adapter
3 | */
4 | import { Injectable } from '@angular/core';
5 | import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
6 | import dayjs from 'dayjs/esm';
7 |
8 | @Injectable()
9 | export class NgbDateDayjsAdapter extends NgbDateAdapter {
10 | fromModel(date: dayjs.Dayjs | null): NgbDateStruct | null {
11 | if (date && dayjs.isDayjs(date) && date.isValid()) {
12 | return { year: date.year(), month: date.month() + 1, day: date.date() };
13 | }
14 | return null;
15 | }
16 |
17 | toModel(date: NgbDateStruct | null): dayjs.Dayjs | null {
18 | return date ? dayjs(`${date.year}-${date.month}-${date.day}`) : null;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/dayjs.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs/esm';
2 | import customParseFormat from 'dayjs/esm/plugin/customParseFormat';
3 | import duration from 'dayjs/esm/plugin/duration';
4 | import relativeTime from 'dayjs/esm/plugin/relativeTime';
5 |
6 | // jhipster-needle-i18n-language-dayjs-imports - JHipster will import languages from dayjs here
7 | import 'dayjs/esm/locale/en';
8 |
9 | // DAYJS CONFIGURATION
10 | dayjs.extend(customParseFormat);
11 | dayjs.extend(duration);
12 | dayjs.extend(relativeTime);
13 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/error.constants.ts:
--------------------------------------------------------------------------------
1 | export const PROBLEM_BASE_URL = 'http://localhost:8080/problem';
2 | export const EMAIL_ALREADY_USED_TYPE = `${PROBLEM_BASE_URL}/email-already-used`;
3 | export const EMAIL_SERVICE_NOT_ALLOWED_TYPE = `${PROBLEM_BASE_URL}/email-service-not-allowed`;
4 | export const LOGIN_ALREADY_USED_TYPE = `${PROBLEM_BASE_URL}/login-already-used`;
5 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/input.constants.ts:
--------------------------------------------------------------------------------
1 | export const DATE_FORMAT = 'YYYY-MM-DD';
2 | export const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm';
3 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/language.constants.ts:
--------------------------------------------------------------------------------
1 | /*
2 | Languages codes are ISO_639-1 codes, see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
3 | They are written in English to avoid character encoding issues (not a perfect solution)
4 | */
5 | export const LANGUAGES: string[] = [
6 | 'en',
7 | // jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array
8 | ];
9 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/navigation.constants.ts:
--------------------------------------------------------------------------------
1 | export const ASC = 'asc';
2 | export const DESC = 'desc';
3 | export const SORT = 'sort';
4 | export const ITEM_DELETED_EVENT = 'deleted';
5 | export const DEFAULT_SORT_DATA = 'defaultSort';
6 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/pagination.constants.ts:
--------------------------------------------------------------------------------
1 | export const TOTAL_COUNT_RESPONSE_HEADER = 'X-Total-Count';
2 | export const PAGE_HEADER = 'page';
3 | export const ITEMS_PER_PAGE = 20;
4 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/translation.config.ts:
--------------------------------------------------------------------------------
1 | import { HttpClient } from '@angular/common/http';
2 | import { MissingTranslationHandler, MissingTranslationHandlerParams, TranslateLoader } from '@ngx-translate/core';
3 | import { TranslateHttpLoader } from '@ngx-translate/http-loader';
4 |
5 | export const translationNotFoundMessage = 'translation-not-found';
6 |
7 | export class MissingTranslationHandlerImpl implements MissingTranslationHandler {
8 | handle(params: MissingTranslationHandlerParams): string {
9 | const key = params.key;
10 | return `${translationNotFoundMessage}[${key}]`;
11 | }
12 | }
13 |
14 | export function translatePartialLoader(http: HttpClient): TranslateLoader {
15 | return new TranslateHttpLoader(http, 'i18n/', `.json?_=${I18N_HASH}`);
16 | }
17 |
18 | export function missingTranslationHandler(): MissingTranslationHandler {
19 | return new MissingTranslationHandlerImpl();
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/uib-pagination.config.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap';
3 |
4 | import { ITEMS_PER_PAGE } from 'app/config/pagination.constants';
5 |
6 | @Injectable({ providedIn: 'root' })
7 | export class PaginationConfig {
8 | private config = inject(NgbPaginationConfig);
9 | constructor() {
10 | this.config.boundaryLinks = true;
11 | this.config.maxSize = 5;
12 | this.config.pageSize = ITEMS_PER_PAGE;
13 | this.config.size = 'sm';
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/auth/account.model.ts:
--------------------------------------------------------------------------------
1 | export class Account {
2 | constructor(
3 | public activated: boolean,
4 | public authorities: string[],
5 | public email: string,
6 | public firstName: string | null,
7 | public langKey: string,
8 | public lastName: string | null,
9 | public login: string,
10 | public imageUrl: string | null,
11 | ) {}
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/config/application-config.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable({
4 | providedIn: 'root',
5 | })
6 | export class ApplicationConfigService {
7 | private endpointPrefix = '';
8 | private microfrontend = false;
9 |
10 | setEndpointPrefix(endpointPrefix: string): void {
11 | this.endpointPrefix = endpointPrefix;
12 | }
13 |
14 | setMicrofrontend(microfrontend = true): void {
15 | this.microfrontend = microfrontend;
16 | }
17 |
18 | isMicrofrontend(): boolean {
19 | return this.microfrontend;
20 | }
21 |
22 | getEndpointFor(api: string, microservice?: string): string {
23 | if (microservice) {
24 | return `${this.endpointPrefix}services/${microservice}/${api}`;
25 | }
26 | return `${this.endpointPrefix}${api}`;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/interceptor/auth-expired.interceptor.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 | import { tap } from 'rxjs/operators';
5 | import { Router } from '@angular/router';
6 |
7 | import { LoginService } from 'app/login/login.service';
8 | import { StateStorageService } from 'app/core/auth/state-storage.service';
9 |
10 | @Injectable()
11 | export class AuthExpiredInterceptor implements HttpInterceptor {
12 | private loginService = inject(LoginService);
13 | private stateStorageService = inject(StateStorageService);
14 | private router = inject(Router);
15 |
16 | intercept(request: HttpRequest, next: HttpHandler): Observable> {
17 | return next.handle(request).pipe(
18 | tap({
19 | error: (err: HttpErrorResponse) => {
20 | if (err.status === 401 && err.url && !err.url.includes('api/account')) {
21 | this.stateStorageService.storeUrl(this.router.routerState.snapshot.url);
22 | this.loginService.logout();
23 | this.router.navigate(['/login']);
24 | }
25 | },
26 | }),
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/interceptor/auth.interceptor.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 |
5 | import { StateStorageService } from 'app/core/auth/state-storage.service';
6 | import { ApplicationConfigService } from '../config/application-config.service';
7 |
8 | @Injectable()
9 | export class AuthInterceptor implements HttpInterceptor {
10 | private stateStorageService = inject(StateStorageService);
11 | private applicationConfigService = inject(ApplicationConfigService);
12 |
13 | intercept(request: HttpRequest, next: HttpHandler): Observable> {
14 | const serverApiUrl = this.applicationConfigService.getEndpointFor('');
15 | if (!request.url || (request.url.startsWith('http') && !(serverApiUrl && request.url.startsWith(serverApiUrl)))) {
16 | return next.handle(request);
17 | }
18 |
19 | const token: string | null = this.stateStorageService.getAuthenticationToken();
20 | if (token) {
21 | request = request.clone({
22 | setHeaders: {
23 | Authorization: `Bearer ${token}`,
24 | },
25 | });
26 | }
27 | return next.handle(request);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/interceptor/error-handler.interceptor.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { HttpInterceptor, HttpRequest, HttpErrorResponse, HttpHandler, HttpEvent } from '@angular/common/http';
3 | import { Observable } from 'rxjs';
4 | import { tap } from 'rxjs/operators';
5 |
6 | import { EventManager, EventWithContent } from 'app/core/util/event-manager.service';
7 |
8 | @Injectable()
9 | export class ErrorHandlerInterceptor implements HttpInterceptor {
10 | private eventManager = inject(EventManager);
11 |
12 | intercept(request: HttpRequest, next: HttpHandler): Observable> {
13 | return next.handle(request).pipe(
14 | tap({
15 | error: (err: HttpErrorResponse) => {
16 | if (!(err.status === 401 && (err.message === '' || err.url?.includes('api/account')))) {
17 | this.eventManager.broadcast(new EventWithContent('webApp.httpError', err));
18 | }
19 | },
20 | }),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/interceptor/index.ts:
--------------------------------------------------------------------------------
1 | import { HTTP_INTERCEPTORS } from '@angular/common/http';
2 |
3 | import { AuthInterceptor } from 'app/core/interceptor/auth.interceptor';
4 | import { AuthExpiredInterceptor } from 'app/core/interceptor/auth-expired.interceptor';
5 | import { ErrorHandlerInterceptor } from 'app/core/interceptor/error-handler.interceptor';
6 | import { NotificationInterceptor } from 'app/core/interceptor/notification.interceptor';
7 |
8 | export const httpInterceptorProviders = [
9 | {
10 | provide: HTTP_INTERCEPTORS,
11 | useClass: AuthInterceptor,
12 | multi: true,
13 | },
14 | {
15 | provide: HTTP_INTERCEPTORS,
16 | useClass: AuthExpiredInterceptor,
17 | multi: true,
18 | },
19 | {
20 | provide: HTTP_INTERCEPTORS,
21 | useClass: ErrorHandlerInterceptor,
22 | multi: true,
23 | },
24 | {
25 | provide: HTTP_INTERCEPTORS,
26 | useClass: NotificationInterceptor,
27 | multi: true,
28 | },
29 | ];
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/request/request-util.ts:
--------------------------------------------------------------------------------
1 | import { HttpParams } from '@angular/common/http';
2 |
3 | export const createRequestOption = (req?: any): HttpParams => {
4 | let options: HttpParams = new HttpParams();
5 |
6 | if (req) {
7 | Object.entries(req).forEach(([key, val]) => {
8 | if (val !== undefined && val !== null) {
9 | for (const value of [].concat(req[key]).filter(v => v !== '')) {
10 | options = options.append(key, value);
11 | }
12 | }
13 | });
14 | }
15 |
16 | return options;
17 | };
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/request/request.model.ts:
--------------------------------------------------------------------------------
1 | export interface Pagination {
2 | page: number;
3 | size: number;
4 | sort: string[];
5 | }
6 |
7 | export interface Search {
8 | query: string;
9 | }
10 |
11 | export interface SearchWithPagination extends Search, Pagination {}
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/tracker/tracker-activity.model.ts:
--------------------------------------------------------------------------------
1 | export class TrackerActivity {
2 | constructor(
3 | public sessionId: string,
4 | public userLogin: string,
5 | public ipAddress: string,
6 | public page: string,
7 | public time: string,
8 | ) {}
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/util/data-util.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { DataUtils } from './data-util.service';
4 |
5 | describe('Data Utils Service Test', () => {
6 | let service: DataUtils;
7 |
8 | beforeEach(() => {
9 | TestBed.configureTestingModule({
10 | providers: [DataUtils],
11 | });
12 | service = TestBed.inject(DataUtils);
13 | });
14 |
15 | describe('byteSize', () => {
16 | it('should return the bytesize of the text', () => {
17 | expect(service.byteSize('Hello JHipster')).toBe(`10.5 bytes`);
18 | });
19 | });
20 |
21 | describe('openFile', () => {
22 | it('should open the file in the new window', () => {
23 | const newWindow = { ...window };
24 | newWindow.document.write = jest.fn();
25 | window.open = jest.fn(() => newWindow);
26 | window.URL.createObjectURL = jest.fn();
27 | // 'JHipster' in base64 is 'SkhpcHN0ZXI='
28 | const data = 'SkhpcHN0ZXI=';
29 | const contentType = 'text/plain';
30 | service.openFile(data, contentType);
31 | expect(window.open).toHaveBeenCalledTimes(1);
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/util/operators.spec.ts:
--------------------------------------------------------------------------------
1 | import { filterNaN, isPresent } from './operators';
2 |
3 | describe('Operators Test', () => {
4 | describe('isPresent', () => {
5 | it('should remove null and undefined values', () => {
6 | expect([1, null, undefined].filter(isPresent)).toEqual([1]);
7 | });
8 | });
9 |
10 | describe('filterNaN', () => {
11 | it('should return 0 for NaN', () => {
12 | expect(filterNaN(NaN)).toBe(0);
13 | });
14 | it('should return number for a number', () => {
15 | expect(filterNaN(12345)).toBe(12345);
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/core/util/operators.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Function used to workaround https://github.com/microsoft/TypeScript/issues/16069
3 | * es2019 alternative `const filteredArr = myArr.flatMap((x) => x ? x : []);`
4 | */
5 | export function isPresent(t: T | undefined | null | void): t is T {
6 | return t !== undefined && t !== null;
7 | }
8 |
9 | export const filterNaN = (input: number): number => (isNaN(input) ? 0 : input);
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/authority.model.ts:
--------------------------------------------------------------------------------
1 | export interface IAuthority {
2 | name: string;
3 | }
4 |
5 | export type NewAuthority = Omit & { name: null };
6 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/authority.test-samples.ts:
--------------------------------------------------------------------------------
1 | import { IAuthority, NewAuthority } from './authority.model';
2 |
3 | export const sampleWithRequiredData: IAuthority = {
4 | name: '0f92069c-b8f6-4580-bb72-2ecd8b2e1f36',
5 | };
6 |
7 | export const sampleWithPartialData: IAuthority = {
8 | name: 'b8c9dd58-1a04-4320-bd74-ee41a1ebdc8c',
9 | };
10 |
11 | export const sampleWithFullData: IAuthority = {
12 | name: 'e1e2bb52-2ef5-411a-be32-fcb0255e649b',
13 | };
14 |
15 | export const sampleWithNewData: NewAuthority = {
16 | name: null,
17 | };
18 |
19 | Object.freeze(sampleWithNewData);
20 | Object.freeze(sampleWithRequiredData);
21 | Object.freeze(sampleWithPartialData);
22 | Object.freeze(sampleWithFullData);
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/delete/authority-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
7 | import { IAuthority } from '../authority.model';
8 | import { AuthorityService } from '../service/authority.service';
9 |
10 | @Component({
11 | standalone: true,
12 | templateUrl: './authority-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export class AuthorityDeleteDialogComponent {
16 | authority?: IAuthority;
17 |
18 | protected authorityService = inject(AuthorityService);
19 | protected activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(id: string): void {
26 | this.authorityService.delete(id).subscribe(() => {
27 | this.activeModal.close(ITEM_DELETED_EVENT);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/detail/authority-detail.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | @if (authority()) {
4 |
5 |
Authority
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | - Name
15 | -
16 | {{ authority()!.name }}
17 |
18 |
19 |
20 |
23 |
24 | }
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/detail/authority-detail.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 |
4 | import SharedModule from 'app/shared/shared.module';
5 | import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
6 | import { IAuthority } from '../authority.model';
7 |
8 | @Component({
9 | standalone: true,
10 | selector: 'jhi-authority-detail',
11 | templateUrl: './authority-detail.component.html',
12 | imports: [SharedModule, RouterModule, DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe],
13 | })
14 | export class AuthorityDetailComponent {
15 | authority = input(null);
16 |
17 | previousState(): void {
18 | window.history.back();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/admin/authority/route/authority-routing-resolve.service.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core';
2 | import { HttpResponse } from '@angular/common/http';
3 | import { ActivatedRouteSnapshot, Router } from '@angular/router';
4 | import { of, EMPTY, Observable } from 'rxjs';
5 | import { mergeMap } from 'rxjs/operators';
6 |
7 | import { IAuthority } from '../authority.model';
8 | import { AuthorityService } from '../service/authority.service';
9 |
10 | const authorityResolve = (route: ActivatedRouteSnapshot): Observable => {
11 | const id = route.params['name'];
12 | if (id) {
13 | return inject(AuthorityService)
14 | .find(id)
15 | .pipe(
16 | mergeMap((authority: HttpResponse) => {
17 | if (authority.body) {
18 | return of(authority.body);
19 | } else {
20 | inject(Router).navigate(['404']);
21 | return EMPTY;
22 | }
23 | }),
24 | );
25 | }
26 | return of(null);
27 | };
28 |
29 | export default authorityResolve;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/delete/detail-delete-dialog.component.html:
--------------------------------------------------------------------------------
1 | @if (detail) {
2 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/delete/detail-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
7 | import { IDetail } from '../detail.model';
8 | import { DetailService } from '../service/detail.service';
9 |
10 | @Component({
11 | standalone: true,
12 | templateUrl: './detail-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export class DetailDeleteDialogComponent {
16 | detail?: IDetail;
17 |
18 | protected detailService = inject(DetailService);
19 | protected activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(id: string): void {
26 | this.detailService.delete(id).subscribe(() => {
27 | this.activeModal.close(ITEM_DELETED_EVENT);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/detail.model.ts:
--------------------------------------------------------------------------------
1 | import { IUser } from 'app/entities/user/user.model';
2 | import { Membership } from 'app/entities/enumerations/membership.model';
3 |
4 | export interface IDetail {
5 | id: string;
6 | discord?: string | null;
7 | sourceId?: string | null;
8 | sourceChannel?: string | null;
9 | total?: string | null;
10 | login?: string | null;
11 | membership?: keyof typeof Membership | null;
12 | user?: Pick | null;
13 | }
14 |
15 | export type NewDetail = Omit & { id: null };
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/detail.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import { DetailComponent } from './list/detail.component';
5 | import { DetailDetailComponent } from './detail/detail-detail.component';
6 | import { DetailUpdateComponent } from './update/detail-update.component';
7 | import DetailResolve from './route/detail-routing-resolve.service';
8 |
9 | const detailRoute: Routes = [
10 | {
11 | path: '',
12 | component: DetailComponent,
13 | data: {},
14 | canActivate: [UserRouteAccessService],
15 | },
16 | {
17 | path: ':id/view',
18 | component: DetailDetailComponent,
19 | resolve: {
20 | detail: DetailResolve,
21 | },
22 | canActivate: [UserRouteAccessService],
23 | },
24 | {
25 | path: 'new',
26 | component: DetailUpdateComponent,
27 | resolve: {
28 | detail: DetailResolve,
29 | },
30 | canActivate: [UserRouteAccessService],
31 | },
32 | {
33 | path: ':id/edit',
34 | component: DetailUpdateComponent,
35 | resolve: {
36 | detail: DetailResolve,
37 | },
38 | canActivate: [UserRouteAccessService],
39 | },
40 | ];
41 |
42 | export default detailRoute;
43 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/detail/detail-detail.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 |
4 | import SharedModule from 'app/shared/shared.module';
5 | import HasAnyAuthorityDirective from 'app/shared/auth/has-any-authority.directive';
6 | import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
7 | import { IDetail } from '../detail.model';
8 |
9 | @Component({
10 | standalone: true,
11 | selector: 'jhi-detail-detail',
12 | templateUrl: './detail-detail.component.html',
13 | imports: [SharedModule, RouterModule, DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe, HasAnyAuthorityDirective],
14 | })
15 | export class DetailDetailComponent {
16 | detail = input(null);
17 |
18 | previousState(): void {
19 | window.history.back();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/detail/route/detail-routing-resolve.service.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core';
2 | import { HttpResponse } from '@angular/common/http';
3 | import { ActivatedRouteSnapshot, Router } from '@angular/router';
4 | import { of, EMPTY, Observable } from 'rxjs';
5 | import { mergeMap } from 'rxjs/operators';
6 |
7 | import { IDetail } from '../detail.model';
8 | import { DetailService } from '../service/detail.service';
9 |
10 | const detailResolve = (route: ActivatedRouteSnapshot): Observable => {
11 | const id = route.params['id'];
12 | if (id) {
13 | return inject(DetailService)
14 | .find(id)
15 | .pipe(
16 | mergeMap((detail: HttpResponse) => {
17 | if (detail.body) {
18 | return of(detail.body);
19 | } else {
20 | inject(Router).navigate(['404']);
21 | return EMPTY;
22 | }
23 | }),
24 | );
25 | }
26 | return of(null);
27 | };
28 |
29 | export default detailResolve;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/entity-navbar-items.ts:
--------------------------------------------------------------------------------
1 | import NavbarItem from 'app/layouts/navbar/navbar-item.model';
2 |
3 | export const EntityNavbarItems: NavbarItem[] = [
4 | {
5 | name: 'Job',
6 | route: '/job',
7 | translationKey: 'global.menu.entities.job',
8 | },
9 | {
10 | name: 'Detail',
11 | route: '/detail',
12 | translationKey: 'global.menu.entities.detail',
13 | },
14 | {
15 | name: 'Type',
16 | route: '/type',
17 | translationKey: 'global.menu.entities.type',
18 | },
19 | ];
20 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/entity.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | const routes: Routes = [
4 | {
5 | path: 'authority',
6 | data: { pageTitle: 'webApp.adminAuthority.home.title' },
7 | loadChildren: () => import('./admin/authority/authority.routes'),
8 | },
9 | {
10 | path: 'job',
11 | data: { pageTitle: 'webApp.job.home.title' },
12 | loadChildren: () => import('./job/job.routes'),
13 | },
14 | {
15 | path: 'detail',
16 | data: { pageTitle: 'webApp.detail.home.title' },
17 | loadChildren: () => import('./detail/detail.routes'),
18 | },
19 | {
20 | path: 'type',
21 | data: { pageTitle: 'webApp.type.home.title' },
22 | loadChildren: () => import('./type/type.routes'),
23 | },
24 | {
25 | path: 'redeem',
26 | data: { pageTitle: 'webApp.redeem.home.title' },
27 | loadChildren: () => import('./redeem/redeem.routes'),
28 | },
29 | /* jhipster-needle-add-entity-route - JHipster will add entity modules routes here */
30 | ];
31 |
32 | export default routes;
33 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/enumerations/job-source.model.ts:
--------------------------------------------------------------------------------
1 | export enum JobSource {
2 | WEB = 'WEB',
3 |
4 | IOS = 'IOS',
5 |
6 | ANDROID = 'ANDROID',
7 |
8 | DISCORD = 'DISCORD',
9 |
10 | PAYPAL = 'PAYPAL',
11 |
12 | PATREON = 'PATREON',
13 |
14 | OTHER = 'OTHER',
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/enumerations/job-status.model.ts:
--------------------------------------------------------------------------------
1 | export enum JobStatus {
2 | POSITIVE = 'POSITIVE',
3 |
4 | NEGATIVE = 'NEGATIVE',
5 |
6 | WAITING = 'WAITING',
7 |
8 | WORKING = 'WORKING',
9 |
10 | DONE = 'DONE',
11 |
12 | FAILED = 'FAILED',
13 |
14 | CANCELED = 'CANCELED',
15 |
16 | EXPIRED = 'EXPIRED',
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/enumerations/membership.model.ts:
--------------------------------------------------------------------------------
1 | export enum Membership {
2 | FREE = 'FREE',
3 |
4 | PAID = 'PAID',
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/enumerations/redeem-status.model.ts:
--------------------------------------------------------------------------------
1 | export enum RedeemStatus {
2 | WAITING = 'WAITING',
3 |
4 | USED = 'USED',
5 |
6 | FAILED = 'FAILED',
7 |
8 | CANCELED = 'CANCELED',
9 |
10 | EXPIRED = 'EXPIRED',
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/delete/job-delete-dialog.component.html:
--------------------------------------------------------------------------------
1 | @if (job) {
2 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/delete/job-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
7 | import { IJob } from '../job.model';
8 | import { JobService } from '../service/job.service';
9 |
10 | @Component({
11 | standalone: true,
12 | templateUrl: './job-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export class JobDeleteDialogComponent {
16 | job?: IJob;
17 |
18 | protected jobService = inject(JobService);
19 | protected activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(id: string): void {
26 | this.jobService.delete(id).subscribe(() => {
27 | this.activeModal.close(ITEM_DELETED_EVENT);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/detail/job-detail.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 |
4 | import SharedModule from 'app/shared/shared.module';
5 | import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
6 | import { IJob } from '../job.model';
7 |
8 | @Component({
9 | standalone: true,
10 | selector: 'jhi-job-detail',
11 | templateUrl: './job-detail.component.html',
12 | imports: [SharedModule, RouterModule, DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe],
13 | })
14 | export class JobDetailComponent {
15 | job = input(null);
16 |
17 | previousState(): void {
18 | window.history.back();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/job.model.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs/esm';
2 | import { IDetail } from 'app/entities/detail/detail.model';
3 | import { IUser } from 'app/entities/user/user.model';
4 | import { JobStatus } from 'app/entities/enumerations/job-status.model';
5 | import { JobSource } from 'app/entities/enumerations/job-source.model';
6 |
7 | export interface IJob {
8 | id: string;
9 | date?: dayjs.Dayjs | null;
10 | status?: keyof typeof JobStatus | null;
11 | source?: keyof typeof JobSource | null;
12 | sourceId?: string | null;
13 | sourceChannel?: string | null;
14 | command?: string | null;
15 | type?: string | null;
16 | amount?: string | null;
17 | result?: string | null;
18 | login?: string | null;
19 | discord?: IDetail | null;
20 | total?: IDetail | null;
21 | user?: Pick | null;
22 | }
23 |
24 | export type NewJob = Omit & { id: null };
25 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/job.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import { JobComponent } from './list/job.component';
5 | import { JobDetailComponent } from './detail/job-detail.component';
6 | import { JobUpdateComponent } from './update/job-update.component';
7 | import JobResolve from './route/job-routing-resolve.service';
8 |
9 | const jobRoute: Routes = [
10 | {
11 | path: '',
12 | component: JobComponent,
13 | data: {},
14 | canActivate: [UserRouteAccessService],
15 | },
16 | {
17 | path: ':id/view',
18 | component: JobDetailComponent,
19 | resolve: {
20 | job: JobResolve,
21 | },
22 | canActivate: [UserRouteAccessService],
23 | },
24 | {
25 | path: 'new',
26 | component: JobUpdateComponent,
27 | resolve: {
28 | job: JobResolve,
29 | },
30 | canActivate: [UserRouteAccessService],
31 | },
32 | {
33 | path: ':id/edit',
34 | component: JobUpdateComponent,
35 | resolve: {
36 | job: JobResolve,
37 | },
38 | canActivate: [UserRouteAccessService],
39 | },
40 | ];
41 |
42 | export default jobRoute;
43 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/job/route/job-routing-resolve.service.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core';
2 | import { HttpResponse } from '@angular/common/http';
3 | import { ActivatedRouteSnapshot, Router } from '@angular/router';
4 | import { of, EMPTY, Observable } from 'rxjs';
5 | import { mergeMap } from 'rxjs/operators';
6 |
7 | import { IJob } from '../job.model';
8 | import { JobService } from '../service/job.service';
9 |
10 | const jobResolve = (route: ActivatedRouteSnapshot): Observable => {
11 | const id = route.params['id'];
12 | if (id) {
13 | return inject(JobService)
14 | .find(id)
15 | .pipe(
16 | mergeMap((job: HttpResponse) => {
17 | if (job.body) {
18 | return of(job.body);
19 | } else {
20 | inject(Router).navigate(['404']);
21 | return EMPTY;
22 | }
23 | }),
24 | );
25 | }
26 | return of(null);
27 | };
28 |
29 | export default jobResolve;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/delete/redeem-delete-dialog.component.html:
--------------------------------------------------------------------------------
1 | @if (redeem) {
2 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/delete/redeem-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
7 | import { IRedeem } from '../redeem.model';
8 | import { RedeemService } from '../service/redeem.service';
9 |
10 | @Component({
11 | standalone: true,
12 | templateUrl: './redeem-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export class RedeemDeleteDialogComponent {
16 | redeem?: IRedeem;
17 |
18 | protected redeemService = inject(RedeemService);
19 | protected activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(id: string): void {
26 | this.redeemService.delete(id).subscribe(() => {
27 | this.activeModal.close(ITEM_DELETED_EVENT);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/detail/redeem-detail.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, input } from '@angular/core';
2 | import { RouterModule } from '@angular/router';
3 |
4 | import SharedModule from 'app/shared/shared.module';
5 | import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
6 | import { IRedeem } from '../redeem.model';
7 |
8 | @Component({
9 | standalone: true,
10 | selector: 'jhi-redeem-detail',
11 | templateUrl: './redeem-detail.component.html',
12 | imports: [SharedModule, RouterModule, DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe],
13 | })
14 | export class RedeemDetailComponent {
15 | redeem = input(null);
16 |
17 | previousState(): void {
18 | window.history.back();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/redeem.model.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs/esm';
2 | import { IUser } from 'app/entities/user/user.model';
3 | import { RedeemStatus } from 'app/entities/enumerations/redeem-status.model';
4 |
5 | export interface IRedeem {
6 | id: string;
7 | date?: dayjs.Dayjs | null;
8 | status?: keyof typeof RedeemStatus | null;
9 | type?: string | null;
10 | author?: string | null;
11 | login?: string | null;
12 | amount?: string | null;
13 | code?: string | null;
14 | user?: Pick | null;
15 | }
16 |
17 | export type NewRedeem = Omit & { id: null };
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/redeem.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import { RedeemComponent } from './list/redeem.component';
5 | import { RedeemDetailComponent } from './detail/redeem-detail.component';
6 | import { RedeemUpdateComponent } from './update/redeem-update.component';
7 | import RedeemResolve from './route/redeem-routing-resolve.service';
8 |
9 | const redeemRoute: Routes = [
10 | {
11 | path: '',
12 | component: RedeemComponent,
13 | data: {},
14 | canActivate: [UserRouteAccessService],
15 | },
16 | {
17 | path: ':id/view',
18 | component: RedeemDetailComponent,
19 | resolve: {
20 | redeem: RedeemResolve,
21 | },
22 | canActivate: [UserRouteAccessService],
23 | },
24 | {
25 | path: 'new',
26 | component: RedeemUpdateComponent,
27 | resolve: {
28 | redeem: RedeemResolve,
29 | },
30 | canActivate: [UserRouteAccessService],
31 | },
32 | {
33 | path: ':id/edit',
34 | component: RedeemUpdateComponent,
35 | resolve: {
36 | redeem: RedeemResolve,
37 | },
38 | canActivate: [UserRouteAccessService],
39 | },
40 | ];
41 |
42 | export default redeemRoute;
43 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/redeem/route/redeem-routing-resolve.service.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core';
2 | import { HttpResponse } from '@angular/common/http';
3 | import { ActivatedRouteSnapshot, Router } from '@angular/router';
4 | import { of, EMPTY, Observable } from 'rxjs';
5 | import { mergeMap } from 'rxjs/operators';
6 |
7 | import { IRedeem } from '../redeem.model';
8 | import { RedeemService } from '../service/redeem.service';
9 |
10 | const redeemResolve = (route: ActivatedRouteSnapshot): Observable => {
11 | const id = route.params['id'];
12 | if (id) {
13 | return inject(RedeemService)
14 | .find(id)
15 | .pipe(
16 | mergeMap((redeem: HttpResponse) => {
17 | if (redeem.body) {
18 | return of(redeem.body);
19 | } else {
20 | inject(Router).navigate(['404']);
21 | return EMPTY;
22 | }
23 | }),
24 | );
25 | }
26 | return of(null);
27 | };
28 |
29 | export default redeemResolve;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/type/delete/type-delete-dialog.component.html:
--------------------------------------------------------------------------------
1 | @if (type) {
2 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/type/delete/type-delete-dialog.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { FormsModule } from '@angular/forms';
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ITEM_DELETED_EVENT } from 'app/config/navigation.constants';
7 | import { IType } from '../type.model';
8 | import { TypeService } from '../service/type.service';
9 |
10 | @Component({
11 | standalone: true,
12 | templateUrl: './type-delete-dialog.component.html',
13 | imports: [SharedModule, FormsModule],
14 | })
15 | export class TypeDeleteDialogComponent {
16 | type?: IType;
17 |
18 | protected typeService = inject(TypeService);
19 | protected activeModal = inject(NgbActiveModal);
20 |
21 | cancel(): void {
22 | this.activeModal.dismiss();
23 | }
24 |
25 | confirmDelete(id: string): void {
26 | this.typeService.delete(id).subscribe(() => {
27 | this.activeModal.close(ITEM_DELETED_EVENT);
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/type/route/type-routing-resolve.service.ts:
--------------------------------------------------------------------------------
1 | import { inject } from '@angular/core';
2 | import { HttpResponse } from '@angular/common/http';
3 | import { ActivatedRouteSnapshot, Router } from '@angular/router';
4 | import { of, EMPTY, Observable } from 'rxjs';
5 | import { mergeMap } from 'rxjs/operators';
6 |
7 | import { IType } from '../type.model';
8 | import { TypeService } from '../service/type.service';
9 |
10 | const typeResolve = (route: ActivatedRouteSnapshot): Observable => {
11 | const id = route.params['id'];
12 | if (id) {
13 | return inject(TypeService)
14 | .find(id)
15 | .pipe(
16 | mergeMap((type: HttpResponse) => {
17 | if (type.body) {
18 | return of(type.body);
19 | } else {
20 | inject(Router).navigate(['404']);
21 | return EMPTY;
22 | }
23 | }),
24 | );
25 | }
26 | return of(null);
27 | };
28 |
29 | export default typeResolve;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/type/type.model.ts:
--------------------------------------------------------------------------------
1 | export interface IType {
2 | id: string;
3 | type?: string | null;
4 | amount?: string | null;
5 | schema?: string | null;
6 | model?: string | null;
7 | title?: string | null;
8 | isDefault?: boolean | null;
9 | isActive?: boolean | null;
10 | isFree?: boolean | null;
11 | cooldown?: string | null;
12 | }
13 |
14 | export type NewType = Omit & { id: null };
15 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/type/type.routes.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
4 | import { TypeComponent } from './list/type.component';
5 | import { TypeDetailComponent } from './detail/type-detail.component';
6 | import { TypeUpdateComponent } from './update/type-update.component';
7 | import TypeResolve from './route/type-routing-resolve.service';
8 |
9 | const typeRoute: Routes = [
10 | {
11 | path: '',
12 | component: TypeComponent,
13 | data: {},
14 | canActivate: [UserRouteAccessService],
15 | },
16 | {
17 | path: ':id/view',
18 | component: TypeDetailComponent,
19 | resolve: {
20 | type: TypeResolve,
21 | },
22 | canActivate: [UserRouteAccessService],
23 | },
24 | {
25 | path: 'new',
26 | component: TypeUpdateComponent,
27 | resolve: {
28 | type: TypeResolve,
29 | },
30 | canActivate: [UserRouteAccessService],
31 | },
32 | {
33 | path: ':id/edit',
34 | component: TypeUpdateComponent,
35 | resolve: {
36 | type: TypeResolve,
37 | },
38 | canActivate: [UserRouteAccessService],
39 | },
40 | ];
41 |
42 | export default typeRoute;
43 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/user/user.model.ts:
--------------------------------------------------------------------------------
1 | export interface IUser {
2 | id: string;
3 | login?: string | null;
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/user/user.test-samples.ts:
--------------------------------------------------------------------------------
1 | import { IUser } from './user.model';
2 |
3 | export const sampleWithRequiredData: IUser = {
4 | id: 'c8d822a6-ea8a-44a3-92a0-68feb8b40b1b',
5 | login: 'EAN@WJV\\0dK\\vC\\NG',
6 | };
7 |
8 | export const sampleWithPartialData: IUser = {
9 | id: '677d5319-42eb-4b73-a4d4-844ca5ca5dde',
10 | login: '0be',
11 | };
12 |
13 | export const sampleWithFullData: IUser = {
14 | id: '2e4654dd-e303-4ccd-95ce-00d86ed1d275',
15 | login: '3?fyv@oxU\\,DfVQG\\30j\\Tlt\\.GItGyV',
16 | };
17 | Object.freeze(sampleWithRequiredData);
18 | Object.freeze(sampleWithPartialData);
19 | Object.freeze(sampleWithFullData);
20 |
--------------------------------------------------------------------------------
/src/main/webapp/app/home/home.component.scss:
--------------------------------------------------------------------------------
1 | /* ==========================================================================
2 | Main page styles
3 | ========================================================================== */
4 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/error/error.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Error page!
5 | @if (errorMessage()) {
6 |
{{ errorMessage() }}
7 | }
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/error/error.route.ts:
--------------------------------------------------------------------------------
1 | import { Routes } from '@angular/router';
2 |
3 | import ErrorComponent from './error.component';
4 |
5 | export const errorRoute: Routes = [
6 | {
7 | path: 'error',
8 | component: ErrorComponent,
9 | title: 'error.title',
10 | },
11 | {
12 | path: 'accessdenied',
13 | component: ErrorComponent,
14 | data: {
15 | errorMessage: 'error.http.403',
16 | },
17 | title: 'error.title',
18 | },
19 | {
20 | path: '404',
21 | component: ErrorComponent,
22 | data: {
23 | errorMessage: 'error.http.404',
24 | },
25 | title: 'error.title',
26 | },
27 | {
28 | path: '**',
29 | redirectTo: '/404',
30 | },
31 | ];
32 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/main/main.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/navbar/active-menu.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, OnInit, ElementRef, Renderer2, inject, Input } from '@angular/core';
2 | import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
3 |
4 | @Directive({
5 | standalone: true,
6 | selector: '[jhiActiveMenu]',
7 | })
8 | export default class ActiveMenuDirective implements OnInit {
9 | @Input() jhiActiveMenu?: string;
10 |
11 | private el = inject(ElementRef);
12 | private renderer = inject(Renderer2);
13 | private translateService = inject(TranslateService);
14 |
15 | ngOnInit(): void {
16 | this.translateService.onLangChange.subscribe((event: LangChangeEvent) => {
17 | this.updateActiveFlag(event.lang);
18 | });
19 |
20 | this.updateActiveFlag(this.translateService.currentLang);
21 | }
22 |
23 | updateActiveFlag(selectedLanguage: string): void {
24 | if (this.jhiActiveMenu === selectedLanguage) {
25 | this.renderer.addClass(this.el.nativeElement, 'active');
26 | } else {
27 | this.renderer.removeClass(this.el.nativeElement, 'active');
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/navbar/navbar-item.model.d.ts:
--------------------------------------------------------------------------------
1 | type NavbarItem = {
2 | name: string;
3 | route: string;
4 | translationKey: string;
5 | };
6 |
7 | export default NavbarItem;
8 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/profiles/page-ribbon.component.scss:
--------------------------------------------------------------------------------
1 | /* ==========================================================================
2 | Development Ribbon
3 | ========================================================================== */
4 | .ribbon {
5 | background-color: rgba(170, 0, 0, 0.5);
6 | overflow: hidden;
7 | position: absolute;
8 | top: 40px;
9 | white-space: nowrap;
10 | width: 15em;
11 | z-index: 9999;
12 | pointer-events: none;
13 | opacity: 0.75;
14 | a {
15 | color: #fff;
16 | display: block;
17 | font-weight: 400;
18 | margin: 1px 0;
19 | padding: 10px 50px;
20 | text-align: center;
21 | text-decoration: none;
22 | text-shadow: 0 0 5px #444;
23 | pointer-events: none;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject, OnInit } from '@angular/core';
2 | import { Observable } from 'rxjs';
3 | import { map } from 'rxjs/operators';
4 |
5 | import SharedModule from 'app/shared/shared.module';
6 | import { ProfileService } from './profile.service';
7 |
8 | @Component({
9 | standalone: true,
10 | selector: 'jhi-page-ribbon',
11 | template: `
12 | @if (ribbonEnv$ | async; as ribbonEnv) {
13 |
16 | }
17 | `,
18 | styleUrl: './page-ribbon.component.scss',
19 | imports: [SharedModule],
20 | })
21 | export default class PageRibbonComponent implements OnInit {
22 | ribbonEnv$?: Observable;
23 |
24 | private profileService = inject(ProfileService);
25 |
26 | ngOnInit(): void {
27 | this.ribbonEnv$ = this.profileService.getProfileInfo().pipe(map(profileInfo => profileInfo.ribbonEnv));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/layouts/profiles/profile-info.model.ts:
--------------------------------------------------------------------------------
1 | export interface InfoResponse {
2 | 'display-ribbon-on-profiles'?: string;
3 | git?: any;
4 | build?: any;
5 | activeProfiles?: string[];
6 | }
7 |
8 | export class ProfileInfo {
9 | constructor(
10 | public activeProfiles?: string[],
11 | public ribbonEnv?: string,
12 | public inProduction?: boolean,
13 | public openAPIEnabled?: boolean,
14 | ) {}
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/login/login.model.ts:
--------------------------------------------------------------------------------
1 | export class Login {
2 | constructor(
3 | public username: string,
4 | public password: string,
5 | public rememberMe: boolean,
6 | ) {}
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/webapp/app/login/login.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import { Observable } from 'rxjs';
3 | import { mergeMap } from 'rxjs/operators';
4 |
5 | import { Account } from 'app/core/auth/account.model';
6 | import { AccountService } from 'app/core/auth/account.service';
7 | import { AuthServerProvider } from 'app/core/auth/auth-jwt.service';
8 | import { Login } from './login.model';
9 |
10 | @Injectable({ providedIn: 'root' })
11 | export class LoginService {
12 | private accountService = inject(AccountService);
13 | private authServerProvider = inject(AuthServerProvider);
14 |
15 | login(credentials: Login): Observable {
16 | return this.authServerProvider.login(credentials).pipe(mergeMap(() => this.accountService.identity(true)));
17 | }
18 |
19 | logout(): void {
20 | this.authServerProvider.logout().subscribe({ complete: () => this.accountService.authenticate(null) });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/alert/alert-error.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (alert of alerts(); track $index) {
3 |
4 | @if (alert.message) {
5 |
6 |
7 |
8 | }
9 |
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/alert/alert-error.model.ts:
--------------------------------------------------------------------------------
1 | export class AlertError {
2 | constructor(
3 | public message: string,
4 | public key?: string,
5 | public params?: { [key: string]: unknown },
6 | ) {}
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/alert/alert.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (alert of alerts(); track $index) {
3 |
4 | @if (alert.message) {
5 |
6 |
7 |
8 | }
9 |
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/alert/alert.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject, OnDestroy, OnInit, signal } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
4 |
5 | import { AlertService, Alert } from 'app/core/util/alert.service';
6 |
7 | @Component({
8 | standalone: true,
9 | selector: 'jhi-alert',
10 | templateUrl: './alert.component.html',
11 | imports: [CommonModule, NgbModule],
12 | })
13 | export class AlertComponent implements OnInit, OnDestroy {
14 | alerts = signal([]);
15 |
16 | private alertService = inject(AlertService);
17 |
18 | ngOnInit(): void {
19 | this.alerts.set(this.alertService.get());
20 | }
21 |
22 | setClasses(alert: Alert): { [key: string]: boolean } {
23 | const classes = { 'jhi-toast': Boolean(alert.toast) };
24 | if (alert.position) {
25 | return { ...classes, [alert.position]: true };
26 | }
27 | return classes;
28 | }
29 |
30 | ngOnDestroy(): void {
31 | this.alertService.clear();
32 | }
33 |
34 | close(alert: Alert): void {
35 | alert.close?.(this.alerts());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/duration.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | import dayjs from 'dayjs/esm';
4 |
5 | @Pipe({
6 | standalone: true,
7 | name: 'duration',
8 | })
9 | export default class DurationPipe implements PipeTransform {
10 | transform(value: any): string {
11 | if (value) {
12 | return dayjs.duration(value).humanize();
13 | }
14 | return '';
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/format-medium-date.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs/esm';
2 |
3 | import FormatMediumDatePipe from './format-medium-date.pipe';
4 |
5 | describe('FormatMediumDatePipe', () => {
6 | const formatMediumDatePipe = new FormatMediumDatePipe();
7 |
8 | it('should return an empty string when receive undefined', () => {
9 | expect(formatMediumDatePipe.transform(undefined)).toBe('');
10 | });
11 |
12 | it('should return an empty string when receive null', () => {
13 | expect(formatMediumDatePipe.transform(null)).toBe('');
14 | });
15 |
16 | it('should format date like this D MMM YYYY', () => {
17 | expect(formatMediumDatePipe.transform(dayjs('2020-11-16').locale('fr'))).toBe('16 Nov 2020');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/format-medium-date.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | import dayjs from 'dayjs/esm';
4 |
5 | @Pipe({
6 | standalone: true,
7 | name: 'formatMediumDate',
8 | })
9 | export default class FormatMediumDatePipe implements PipeTransform {
10 | transform(day: dayjs.Dayjs | null | undefined): string {
11 | return day ? day.format('D MMM YYYY') : '';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/format-medium-datetime.pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import dayjs from 'dayjs/esm';
2 |
3 | import FormatMediumDatetimePipe from './format-medium-datetime.pipe';
4 |
5 | describe('FormatMediumDatePipe', () => {
6 | const formatMediumDatetimePipe = new FormatMediumDatetimePipe();
7 |
8 | it('should return an empty string when receive undefined', () => {
9 | expect(formatMediumDatetimePipe.transform(undefined)).toBe('');
10 | });
11 |
12 | it('should return an empty string when receive null', () => {
13 | expect(formatMediumDatetimePipe.transform(null)).toBe('');
14 | });
15 |
16 | it('should format date like this D MMM YYYY', () => {
17 | expect(formatMediumDatetimePipe.transform(dayjs('2020-11-16').locale('fr'))).toBe('16 Nov 2020 00:00:00');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/format-medium-datetime.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | import dayjs from 'dayjs/esm';
4 |
5 | @Pipe({
6 | standalone: true,
7 | name: 'formatMediumDatetime',
8 | })
9 | export default class FormatMediumDatetimePipe implements PipeTransform {
10 | transform(day: dayjs.Dayjs | null | undefined): string {
11 | return day ? day.format('D MMM YYYY HH:mm:ss') : '';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/date/index.ts:
--------------------------------------------------------------------------------
1 | export { default as DurationPipe } from './duration.pipe';
2 | export { default as FormatMediumDatePipe } from './format-medium-date.pipe';
3 | export { default as FormatMediumDatetimePipe } from './format-medium-datetime.pipe';
4 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/filter/filter.component.html:
--------------------------------------------------------------------------------
1 | @if (filters.hasAnyFilterSet()) {
2 |
3 |
Following filters are set
4 |
5 |
6 | @for (filterOption of filters.filterOptions; track filterOption.name) {
7 | @for (value of filterOption.values; track value) {
8 | -
9 | {{ filterOption.name }}: {{ value }}
10 |
15 |
16 | }
17 | }
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/filter/filter.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import SharedModule from '../shared.module';
3 | import { IFilterOptions } from './filter.model';
4 |
5 | @Component({
6 | standalone: true,
7 | selector: 'jhi-filter',
8 | imports: [SharedModule],
9 | templateUrl: './filter.component.html',
10 | })
11 | export default class FilterComponent {
12 | @Input() filters!: IFilterOptions;
13 |
14 | clearAllFilters(): void {
15 | this.filters.clear();
16 | }
17 |
18 | clearFilter(filterName: string, value: string): void {
19 | this.filters.removeFilter(filterName, value);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/filter/index.ts:
--------------------------------------------------------------------------------
1 | export { default as FilterComponent } from './filter.component';
2 | export * from './filter.model';
3 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/language/find-language-from-key.pipe.ts:
--------------------------------------------------------------------------------
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
4 | standalone: true,
5 | name: 'findLanguageFromKey',
6 | })
7 | export default class FindLanguageFromKeyPipe implements PipeTransform {
8 | private languages: { [key: string]: { name: string; rtl?: boolean } } = {
9 | en: { name: 'English' },
10 | // jhipster-needle-i18n-language-key-pipe - JHipster will add/remove languages in this object
11 | };
12 |
13 | transform(lang: string): string {
14 | return this.languages[lang].name;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/language/index.ts:
--------------------------------------------------------------------------------
1 | export { default as TranslateDirective } from './translate.directive';
2 | export { default as FindLanguageFromKeyPipe } from './find-language-from-key.pipe';
3 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/language/translate.directive.spec.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
3 | import { TranslateModule, TranslateService } from '@ngx-translate/core';
4 |
5 | import TranslateDirective from './translate.directive';
6 |
7 | @Component({
8 | template: ` `,
9 | })
10 | class TestTranslateDirectiveComponent {}
11 |
12 | describe('TranslateDirective Tests', () => {
13 | let fixture: ComponentFixture;
14 | let translateService: TranslateService;
15 |
16 | beforeEach(waitForAsync(() => {
17 | TestBed.configureTestingModule({
18 | imports: [TranslateModule.forRoot(), TranslateDirective],
19 | declarations: [TestTranslateDirectiveComponent],
20 | });
21 | }));
22 |
23 | beforeEach(() => {
24 | translateService = TestBed.inject(TranslateService);
25 | fixture = TestBed.createComponent(TestTranslateDirectiveComponent);
26 | });
27 |
28 | it('should change HTML', () => {
29 | const spy = jest.spyOn(translateService, 'get');
30 |
31 | fixture.detectChanges();
32 |
33 | expect(spy).toHaveBeenCalled();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/pagination/index.ts:
--------------------------------------------------------------------------------
1 | export { default as ItemCountComponent } from './item-count.component';
2 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/sort/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sort-by.directive';
2 | export * from './sort-state';
3 | export * from './sort.directive';
4 | export * from './sort.service';
5 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/sort/sort-state.ts:
--------------------------------------------------------------------------------
1 | import { signal, Signal, WritableSignal } from '@angular/core';
2 |
3 | export type SortOrder = 'asc' | 'desc';
4 |
5 | export type SortState = { predicate?: string; order?: SortOrder };
6 |
7 | export type SortStateSignal = Signal;
8 |
9 | export const sortStateSignal = (state: SortState): WritableSignal =>
10 | signal(state, {
11 | equal: (a, b) => a.predicate === b.predicate && a.order === b.order,
12 | });
13 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/sort/sort.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, EventEmitter, Input, Output } from '@angular/core';
2 | import { SortOrder, SortState, SortStateSignal } from './sort-state';
3 |
4 | export interface SortChangeDirective {
5 | sortChange: EventEmitter;
6 |
7 | sort(field: T): void;
8 | }
9 |
10 | @Directive({
11 | standalone: true,
12 | selector: '[jhiSort]',
13 | })
14 | export class SortDirective implements SortChangeDirective {
15 | @Input() sortState!: SortStateSignal;
16 |
17 | @Output() sortChange = new EventEmitter();
18 |
19 | sort(field: string): void {
20 | const { predicate, order } = this.sortState();
21 | const toggle = (): SortOrder => (order === 'asc' ? 'desc' : 'asc');
22 | this.sortChange.emit({ predicate: field, order: field !== predicate ? 'asc' : toggle() });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/widgets/MyWidgetRegistry.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { DefaultWidgetRegistry } from 'ngx-schema-form';
3 | import { ButtonWidget } from './button.widget';
4 | import { ReadmeWidget } from './readme.widget';
5 | import { ChatWidget } from './chat.widget';
6 |
7 | @Injectable()
8 | export class MyWidgetRegistry extends DefaultWidgetRegistry {
9 | constructor() {
10 | super();
11 | this.register('button', ButtonWidget);
12 | this.register('readme', ReadmeWidget);
13 | this.register('chat', ChatWidget);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/widgets/button.widget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/widgets/button.widget.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import { Component, AfterViewInit } from '@angular/core';
3 |
4 | @Component({
5 | selector: 'sf-button-widget',
6 | templateUrl: 'button.widget.html',
7 | })
8 | export class ButtonWidget implements AfterViewInit {
9 | button: any;
10 | formProperty: any;
11 |
12 | ngAfterViewInit(): void {
13 | const llmButtons = document.querySelectorAll('.llm') as NodeListOf;
14 | if (this.formProperty.findRoot().getProperty('chat')) {
15 | llmButtons.forEach((button: HTMLButtonElement) => {
16 | button.style.display = 'none';
17 | });
18 | } else {
19 | llmButtons.forEach((button: HTMLButtonElement) => {
20 | button.style.display = 'block';
21 | });
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/widgets/readme.widget.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/widgets/readme.widget.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import { Component } from '@angular/core';
3 | import { ControlWidget } from 'ngx-schema-form';
4 | import { CommonModule } from '@angular/common';
5 |
6 | @Component({
7 | standalone: true,
8 | selector: 'sf-readme-widget',
9 | templateUrl: 'readme.widget.html',
10 | imports: [CommonModule],
11 | })
12 | export class ReadmeWidget extends ControlWidget {}
13 |
--------------------------------------------------------------------------------
/src/main/webapp/bootstrap.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { bootstrapApplication } from '@angular/platform-browser';
3 | import { appConfig } from './app/app.config';
4 | import AppComponent from './app/app.component';
5 |
6 | import { DEBUG_INFO_ENABLED } from './app/app.constants';
7 |
8 | // disable debug data on prod profile to improve performance
9 | if (!DEBUG_INFO_ENABLED) {
10 | enableProdMode();
11 | }
12 |
13 | bootstrapApplication(AppComponent, appConfig)
14 | // eslint-disable-next-line no-console
15 | .then(() => console.log('Application started'))
16 | .catch(err => console.error(err));
17 |
--------------------------------------------------------------------------------
/src/main/webapp/content/images/generating.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/webapp/content/images/generating.jpg
--------------------------------------------------------------------------------
/src/main/webapp/content/images/logo-jhipster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/webapp/content/images/logo-jhipster.png
--------------------------------------------------------------------------------
/src/main/webapp/content/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/webapp/content/images/logo.png
--------------------------------------------------------------------------------
/src/main/webapp/content/scss/_bootstrap-variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Bootstrap overrides https://getbootstrap.com/docs/5.1/customize/sass/
3 | * All values defined in bootstrap source
4 | * https://github.com/twbs/bootstrap/blob/v5.1.3/scss/_variables.scss can be overwritten here
5 | * Make sure not to add !default to values here
6 | */
7 |
--------------------------------------------------------------------------------
/src/main/webapp/content/scss/vendor.scss:
--------------------------------------------------------------------------------
1 | /* after changing this file run 'npm run webapp:build' */
2 |
3 | /***************************
4 | put Sass variables here:
5 | eg $input-color: red;
6 | ****************************/
7 | @import 'bootswatch/dist/darkly/variables';
8 | // Override Bootstrap variables
9 | @import 'bootstrap-variables';
10 | // Import Bootstrap source files from node_modules
11 | @import 'bootstrap/scss/bootstrap';
12 | @import 'bootswatch/dist/darkly/bootswatch';
13 |
14 | /* jhipster-needle-scss-add-vendor JHipster will add new css style */
15 |
--------------------------------------------------------------------------------
/src/main/webapp/declarations.d.ts:
--------------------------------------------------------------------------------
1 | declare const SERVER_API_URL: string;
2 | declare const I18N_HASH: string;
3 |
--------------------------------------------------------------------------------
/src/main/webapp/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/webapp/favicon.ico
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/activate.json:
--------------------------------------------------------------------------------
1 | {
2 | "activate": {
3 | "title": "Activation",
4 | "messages": {
5 | "success": "Your user account has been activated. Please ",
6 | "error": "Your user could not be activated. Please use the registration form to sign up."
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/adminAuthority.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "adminAuthority": {
4 | "home": {
5 | "title": "Authorities",
6 | "refreshListLabel": "Refresh list",
7 | "createLabel": "Create a new Authority",
8 | "createOrEditLabel": "Create or edit a Authority",
9 | "notFound": "No Authorities found"
10 | },
11 | "created": "A new Authority is created with identifier {{ param }}",
12 | "updated": "A Authority is updated with identifier {{ param }}",
13 | "deleted": "A Authority is deleted with identifier {{ param }}",
14 | "delete": {
15 | "question": "Are you sure you want to delete Authority {{ id }}?"
16 | },
17 | "detail": {
18 | "title": "Authority"
19 | },
20 | "name": "Name"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/configuration.json:
--------------------------------------------------------------------------------
1 | {
2 | "configuration": {
3 | "title": "Configuration",
4 | "filter": "Filter (by prefix)",
5 | "table": {
6 | "prefix": "Prefix",
7 | "properties": "Properties"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "detail": {
4 | "home": {
5 | "title": "Details",
6 | "refreshListLabel": "Refresh list",
7 | "createLabel": "Create a new Detail",
8 | "createOrEditLabel": "Create or edit a Detail",
9 | "notFound": "No Details found"
10 | },
11 | "created": "A new Detail is created with identifier {{ param }}",
12 | "updated": "A Detail is updated with identifier {{ param }}",
13 | "deleted": "A Detail is deleted with identifier {{ param }}",
14 | "delete": {
15 | "question": "Are you sure you want to delete Detail {{ id }}?"
16 | },
17 | "detail": {
18 | "title": "Detail"
19 | },
20 | "id": "ID",
21 | "discord": "Discord",
22 | "sourceId": "Source Id",
23 | "sourceChannel": "Source Channel",
24 | "total": "Total",
25 | "login": "Login",
26 | "membership": "Membership",
27 | "user": "User"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/error.json:
--------------------------------------------------------------------------------
1 | {
2 | "error": {
3 | "title": "Error page!",
4 | "http": {
5 | "400": "Bad request.",
6 | "403": "You are not authorized to access this page.",
7 | "404": "The page does not exist.",
8 | "405": "The HTTP verb you used is not supported for this URL.",
9 | "500": "Internal server error."
10 | },
11 | "concurrencyFailure": "Another user modified this data at the same time as you. Your changes were rejected.",
12 | "validation": "Validation error on the server."
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/health.json:
--------------------------------------------------------------------------------
1 | {
2 | "health": {
3 | "title": "Health Checks",
4 | "refresh.button": "Refresh",
5 | "stacktrace": "Stacktrace",
6 | "details": {
7 | "details": "Details",
8 | "properties": "Properties",
9 | "name": "Name",
10 | "value": "Value",
11 | "error": "Error"
12 | },
13 | "indicator": {
14 | "diskSpace": "Disk space",
15 | "mail": "Email",
16 | "livenessState": "Liveness state",
17 | "readinessState": "Readiness state",
18 | "ping": "Application",
19 | "mongo": "MongoDB"
20 | },
21 | "table": {
22 | "service": "Service name",
23 | "status": "Status"
24 | },
25 | "status": {
26 | "UNKNOWN": "UNKNOWN",
27 | "UP": "UP",
28 | "OUT_OF_SERVICE": "OUT_OF_SERVICE",
29 | "DOWN": "DOWN"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/home.json:
--------------------------------------------------------------------------------
1 | {
2 | "home": {
3 | "title": "Tost AI",
4 | "subtitle": "This is your homepage",
5 | "logged": {
6 | "message": "You are logged in as user \"{{username}}\"."
7 | },
8 | "question": "If you have any question on Tost AI:",
9 | "link": {
10 | "homepage": "Tost AI homepage",
11 | "stackoverflow": "Tost AI on Stack Overflow",
12 | "bugtracker": "Tost AI bug tracker",
13 | "chat": "Tost AI public chat room",
14 | "follow": "follow @tost_ai on Twitter"
15 | },
16 | "like": "If you like Tost AI, don't forget to give us a star on",
17 | "github": "GitHub"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/job.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "job": {
4 | "home": {
5 | "title": "Jobs",
6 | "refreshListLabel": "Refresh list",
7 | "createLabel": "Create a new Job",
8 | "createOrEditLabel": "Create or edit a Job",
9 | "notFound": "No Jobs found"
10 | },
11 | "created": "A new Job is created with identifier {{ param }}",
12 | "updated": "A Job is updated with identifier {{ param }}",
13 | "deleted": "A Job is deleted with identifier {{ param }}",
14 | "delete": {
15 | "question": "Are you sure you want to delete Job {{ id }}?"
16 | },
17 | "detail": {
18 | "title": "Job"
19 | },
20 | "id": "ID",
21 | "date": "Date",
22 | "status": "Status",
23 | "source": "Source",
24 | "sourceId": "Source Id",
25 | "sourceChannel": "Source Channel",
26 | "command": "Command",
27 | "type": "Type",
28 | "amount": "Amount",
29 | "result": "Result",
30 | "login": "Login",
31 | "discord": "Discord",
32 | "total": "Total",
33 | "user": "User"
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/jobSource.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "JobSource": {
4 | "null": "",
5 | "WEB": "WEB",
6 | "IOS": "IOS",
7 | "ANDROID": "ANDROID",
8 | "DISCORD": "DISCORD",
9 | "PAYPAL": "PAYPAL",
10 | "PATREON": "PATREON",
11 | "OTHER": "OTHER"
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/jobStatus.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "JobStatus": {
4 | "null": "",
5 | "POSITIVE": "POSITIVE",
6 | "NEGATIVE": "NEGATIVE",
7 | "WAITING": "WAITING",
8 | "WORKING": "WORKING",
9 | "DONE": "DONE",
10 | "FAILED": "FAILED",
11 | "CANCELED": "CANCELED",
12 | "EXPIRED": "EXPIRED"
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "login": {
3 | "title": "Sign in",
4 | "form": {
5 | "password": "Password",
6 | "password.placeholder": "Your password",
7 | "rememberme": "Remember me",
8 | "button": "Sign in"
9 | },
10 | "messages": {
11 | "error": {
12 | "authentication": "Failed to sign in! Please check your credentials and try again."
13 | }
14 | },
15 | "password": {
16 | "forgot": "Did you forget your password?"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "logs": {
3 | "title": "Logs",
4 | "nbloggers": "There are {{ total }} loggers.",
5 | "filter": "Filter",
6 | "table": {
7 | "name": "Name",
8 | "level": "Level"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/membership.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "Membership": {
4 | "null": "",
5 | "FREE": "FREE",
6 | "PAID": "PAID"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/password.json:
--------------------------------------------------------------------------------
1 | {
2 | "password": {
3 | "title": "Password for [{{username}}]",
4 | "form": {
5 | "button": "Save"
6 | },
7 | "messages": {
8 | "error": "An error has occurred! The password could not be changed.",
9 | "success": "Password changed!"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/redeem.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "redeem": {
4 | "home": {
5 | "title": "Redeems",
6 | "refreshListLabel": "Refresh list",
7 | "createLabel": "Create a new Redeem",
8 | "createOrEditLabel": "Create or edit a Redeem",
9 | "notFound": "No Redeems found"
10 | },
11 | "created": "A new Redeem is created with identifier {{ param }}",
12 | "updated": "A Redeem is updated with identifier {{ param }}",
13 | "deleted": "A Redeem is deleted with identifier {{ param }}",
14 | "delete": {
15 | "question": "Are you sure you want to delete Redeem {{ id }}?"
16 | },
17 | "detail": {
18 | "title": "Redeem"
19 | },
20 | "id": "ID",
21 | "date": "Date",
22 | "status": "Status",
23 | "type": "Type",
24 | "author": "Author",
25 | "login": "Login",
26 | "amount": "Amount",
27 | "code": "Code",
28 | "user": "User"
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/redeemStatus.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "RedeemStatus": {
4 | "null": "",
5 | "WAITING": "WAITING",
6 | "USED": "USED",
7 | "FAILED": "FAILED",
8 | "CANCELED": "CANCELED",
9 | "EXPIRED": "EXPIRED"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/register.json:
--------------------------------------------------------------------------------
1 | {
2 | "register": {
3 | "title": "Registration",
4 | "form": {
5 | "button": "Register"
6 | },
7 | "messages": {
8 | "validate": {
9 | "login": {
10 | "required": "Your username is required.",
11 | "minlength": "Your username is required to be at least 1 character.",
12 | "maxlength": "Your username cannot be longer than 50 characters.",
13 | "pattern": "Your username is invalid."
14 | }
15 | },
16 | "success": "Registration saved! Please check your email for confirmation.",
17 | "error": {
18 | "fail": "Registration failed! Please try again later.",
19 | "userexists": "Login name already registered! Please choose another one.",
20 | "emailexists": "Email is already in use! Please choose another one.",
21 | "emailservicenotallowed": "Email service is not allowed! Please choose another one."
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/reset.json:
--------------------------------------------------------------------------------
1 | {
2 | "reset": {
3 | "request": {
4 | "title": "Reset your password",
5 | "form": {
6 | "button": "Reset password"
7 | },
8 | "messages": {
9 | "info": "Enter the email address you used to register",
10 | "success": "Check your email for details on how to reset your password."
11 | }
12 | },
13 | "finish": {
14 | "title": "Reset password",
15 | "form": {
16 | "button": "Validate new password"
17 | },
18 | "messages": {
19 | "info": "Choose a new password",
20 | "success": "Your password has been reset. Please ",
21 | "keymissing": "The reset key is missing.",
22 | "error": "Your password couldn't be reset. Remember a password request is only valid for 24 hours."
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/sessions.json:
--------------------------------------------------------------------------------
1 | {
2 | "sessions": {
3 | "title": "Active sessions for [{{username}}]",
4 | "table": {
5 | "ipaddress": "IP address",
6 | "useragent": "User Agent",
7 | "date": "Date",
8 | "button": "Invalidate"
9 | },
10 | "messages": {
11 | "success": "Session invalidated!",
12 | "error": "An error has occurred! The session could not be invalidated."
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "settings": {
3 | "title": "User settings for [{{username}}]",
4 | "form": {
5 | "firstname": "First Name",
6 | "firstname.placeholder": "Your first name",
7 | "lastname": "Last Name",
8 | "lastname.placeholder": "Your last name",
9 | "language": "Language",
10 | "button": "Save"
11 | },
12 | "messages": {
13 | "error": {
14 | "fail": "An error has occurred! Settings could not be saved.",
15 | "emailexists": "Email is already in use! Please choose another one."
16 | },
17 | "success": "Settings saved!",
18 | "validate": {
19 | "firstname": {
20 | "required": "Your first name is required.",
21 | "minlength": "Your first name is required to be at least 1 character",
22 | "maxlength": "Your first name cannot be longer than 50 characters"
23 | },
24 | "lastname": {
25 | "required": "Your last name is required.",
26 | "minlength": "Your last name is required to be at least 1 character",
27 | "maxlength": "Your last name cannot be longer than 50 characters"
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/tracker.json:
--------------------------------------------------------------------------------
1 | {
2 | "tracker": {
3 | "title": "Real-time user activities",
4 | "table": {
5 | "userlogin": "User",
6 | "ipaddress": "IP Address",
7 | "userAgent": "User agent",
8 | "page": "Current page",
9 | "time": "Time"
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/type.json:
--------------------------------------------------------------------------------
1 | {
2 | "webApp": {
3 | "type": {
4 | "home": {
5 | "title": "Types",
6 | "refreshListLabel": "Refresh list",
7 | "createLabel": "Create a new Type",
8 | "createOrEditLabel": "Create or edit a Type",
9 | "notFound": "No Types found"
10 | },
11 | "created": "A new Type is created with identifier {{ param }}",
12 | "updated": "A Type is updated with identifier {{ param }}",
13 | "deleted": "A Type is deleted with identifier {{ param }}",
14 | "delete": {
15 | "question": "Are you sure you want to delete Type {{ id }}?"
16 | },
17 | "detail": {
18 | "title": "Type"
19 | },
20 | "id": "ID",
21 | "type": "Type",
22 | "amount": "Amount",
23 | "schema": "Schema",
24 | "model": "Model",
25 | "title": "Title",
26 | "isDefault": "Is Default",
27 | "isActive": "Is Active",
28 | "isFree": "Is Free",
29 | "cooldown": "Cooldown"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/webapp/i18n/en/user-management.json:
--------------------------------------------------------------------------------
1 | {
2 | "userManagement": {
3 | "home": {
4 | "title": "Users",
5 | "refreshListLabel": "Refresh list",
6 | "createLabel": "Create a new user",
7 | "createOrEditLabel": "Create or edit a user"
8 | },
9 | "created": "A new user is created with identifier {{ param }}",
10 | "updated": "A user is updated with identifier {{ param }}",
11 | "deleted": "A user is deleted with identifier {{ param }}",
12 | "delete": {
13 | "question": "Are you sure you want to delete user {{ login }}?"
14 | },
15 | "detail": {
16 | "title": "User"
17 | },
18 | "login": "Login",
19 | "firstName": "First name",
20 | "lastName": "Last name",
21 | "email": "Email",
22 | "activated": "Activated",
23 | "deactivated": "Deactivated",
24 | "profiles": "Profiles",
25 | "langKey": "Language",
26 | "createdBy": "Created by",
27 | "createdDate": "Created date",
28 | "lastModifiedBy": "Modified by",
29 | "lastModifiedDate": "Modified date"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/webapp/main.ts:
--------------------------------------------------------------------------------
1 | import('./bootstrap').catch(err => console.error(err));
2 |
--------------------------------------------------------------------------------
/src/main/webapp/manifest.webapp:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Tost AI",
3 | "short_name": "Tost AI",
4 | "icons": [
5 | {
6 | "src": "./content/images/logo-jhipster.png",
7 | "sizes": "128x128",
8 | "type": "image/png"
9 | }
10 | ],
11 | "theme_color": "#000000",
12 | "background_color": "#e0e0e0",
13 | "start_url": ".",
14 | "display": "standalone",
15 | "orientation": "portrait"
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/webapp/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org/
2 |
3 | User-agent: *
4 | Disallow: /api/account
5 | Disallow: /api/account/change-password
6 | Disallow: /api/account/sessions
7 | Disallow: /api/logs/
8 | Disallow: /api/users/
9 | Disallow: /management/
10 | Disallow: /v3/api-docs/
11 |
--------------------------------------------------------------------------------
/src/main/webapp/sockjs-client.polyfill.ts:
--------------------------------------------------------------------------------
1 | (window as any).global = window;
2 |
--------------------------------------------------------------------------------
/src/main/webapp/swagger-ui/dist/images/throbber.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/main/webapp/swagger-ui/dist/images/throbber.gif
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/IntegrationTest.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web;
2 |
3 | import com.camenduru.web.config.AsyncSyncConfiguration;
4 | import com.camenduru.web.config.EmbeddedMongo;
5 | import com.camenduru.web.config.JacksonConfiguration;
6 | import java.lang.annotation.ElementType;
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.lang.annotation.Target;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 |
12 | /**
13 | * Base composite annotation for integration tests.
14 | */
15 | @Target(ElementType.TYPE)
16 | @Retention(RetentionPolicy.RUNTIME)
17 | @SpringBootTest(classes = { WebApp.class, JacksonConfiguration.class, AsyncSyncConfiguration.class })
18 | @EmbeddedMongo
19 | public @interface IntegrationTest {
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/config/AsyncSyncConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import java.util.concurrent.Executor;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.core.task.SyncTaskExecutor;
7 |
8 | @Configuration
9 | public class AsyncSyncConfiguration {
10 |
11 | @Bean(name = "taskExecutor")
12 | public Executor taskExecutor() {
13 | return new SyncTaskExecutor();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/config/EmbeddedMongo.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target(ElementType.TYPE)
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface EmbeddedMongo {
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/config/SpringBootTestClassOrderer.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import com.camenduru.web.IntegrationTest;
4 | import java.util.Comparator;
5 | import org.junit.jupiter.api.ClassDescriptor;
6 | import org.junit.jupiter.api.ClassOrderer;
7 | import org.junit.jupiter.api.ClassOrdererContext;
8 |
9 | public class SpringBootTestClassOrderer implements ClassOrderer {
10 |
11 | @Override
12 | public void orderClasses(ClassOrdererContext context) {
13 | context.getClassDescriptors().sort(Comparator.comparingInt(SpringBootTestClassOrderer::getOrder));
14 | }
15 |
16 | private static int getOrder(ClassDescriptor classDescriptor) {
17 | if (classDescriptor.findAnnotation(IntegrationTest.class).isPresent()) {
18 | return 2;
19 | }
20 | return 1;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/config/WebConfigurerTestController.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.config;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | @RestController
7 | public class WebConfigurerTestController {
8 |
9 | @GetMapping("/api/test-cors")
10 | public void testCorsOnApiPath() {}
11 |
12 | @GetMapping("/test/test-cors")
13 | public void testCorsOnOtherPath() {}
14 | }
15 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/AssertUtils.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import java.math.BigDecimal;
4 | import java.time.ZoneOffset;
5 | import java.time.ZonedDateTime;
6 | import java.util.Comparator;
7 |
8 | public class AssertUtils {
9 |
10 | public static Comparator zonedDataTimeSameInstant = Comparator.nullsFirst(
11 | (e1, a2) -> e1.withZoneSameInstant(ZoneOffset.UTC).compareTo(a2.withZoneSameInstant(ZoneOffset.UTC))
12 | );
13 |
14 | public static Comparator bigDecimalCompareTo = Comparator.nullsFirst((e1, a2) -> e1.compareTo(a2));
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/AuthorityTest.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import static com.camenduru.web.domain.AuthorityTestSamples.*;
4 | import static org.assertj.core.api.Assertions.assertThat;
5 |
6 | import com.camenduru.web.web.rest.TestUtil;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class AuthorityTest {
10 |
11 | @Test
12 | void equalsVerifier() throws Exception {
13 | TestUtil.equalsVerifier(Authority.class);
14 | Authority authority1 = getAuthoritySample1();
15 | Authority authority2 = new Authority();
16 | assertThat(authority1).isNotEqualTo(authority2);
17 |
18 | authority2.setName(authority1.getName());
19 | assertThat(authority1).isEqualTo(authority2);
20 |
21 | authority2 = getAuthoritySample2();
22 | assertThat(authority1).isNotEqualTo(authority2);
23 | }
24 |
25 | @Test
26 | void hashCodeVerifier() throws Exception {
27 | Authority authority = new Authority();
28 | assertThat(authority.hashCode()).isZero();
29 |
30 | Authority authority1 = getAuthoritySample1();
31 | authority.setName(authority1.getName());
32 | assertThat(authority).hasSameHashCodeAs(authority1);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/AuthorityTestSamples.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import java.util.UUID;
4 |
5 | public class AuthorityTestSamples {
6 |
7 | public static Authority getAuthoritySample1() {
8 | return new Authority().name("name1");
9 | }
10 |
11 | public static Authority getAuthoritySample2() {
12 | return new Authority().name("name2");
13 | }
14 |
15 | public static Authority getAuthorityRandomSampleGenerator() {
16 | return new Authority().name(UUID.randomUUID().toString());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/DetailTest.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import static com.camenduru.web.domain.DetailTestSamples.*;
4 | import static org.assertj.core.api.Assertions.assertThat;
5 |
6 | import com.camenduru.web.web.rest.TestUtil;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class DetailTest {
10 |
11 | @Test
12 | void equalsVerifier() throws Exception {
13 | TestUtil.equalsVerifier(Detail.class);
14 | Detail detail1 = getDetailSample1();
15 | Detail detail2 = new Detail();
16 | assertThat(detail1).isNotEqualTo(detail2);
17 |
18 | detail2.setId(detail1.getId());
19 | assertThat(detail1).isEqualTo(detail2);
20 |
21 | detail2 = getDetailSample2();
22 | assertThat(detail1).isNotEqualTo(detail2);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/DetailTestSamples.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import java.util.UUID;
4 |
5 | public class DetailTestSamples {
6 |
7 | public static Detail getDetailSample1() {
8 | return new Detail()
9 | .id("id1")
10 | .discord("discord1")
11 | .sourceId("sourceId1")
12 | .sourceChannel("sourceChannel1")
13 | .total("total1")
14 | .login("login1");
15 | }
16 |
17 | public static Detail getDetailSample2() {
18 | return new Detail()
19 | .id("id2")
20 | .discord("discord2")
21 | .sourceId("sourceId2")
22 | .sourceChannel("sourceChannel2")
23 | .total("total2")
24 | .login("login2");
25 | }
26 |
27 | public static Detail getDetailRandomSampleGenerator() {
28 | return new Detail()
29 | .id(UUID.randomUUID().toString())
30 | .discord(UUID.randomUUID().toString())
31 | .sourceId(UUID.randomUUID().toString())
32 | .sourceChannel(UUID.randomUUID().toString())
33 | .total(UUID.randomUUID().toString())
34 | .login(UUID.randomUUID().toString());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/RedeemTest.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import static com.camenduru.web.domain.RedeemTestSamples.*;
4 | import static org.assertj.core.api.Assertions.assertThat;
5 |
6 | import com.camenduru.web.web.rest.TestUtil;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class RedeemTest {
10 |
11 | @Test
12 | void equalsVerifier() throws Exception {
13 | TestUtil.equalsVerifier(Redeem.class);
14 | Redeem redeem1 = getRedeemSample1();
15 | Redeem redeem2 = new Redeem();
16 | assertThat(redeem1).isNotEqualTo(redeem2);
17 |
18 | redeem2.setId(redeem1.getId());
19 | assertThat(redeem1).isEqualTo(redeem2);
20 |
21 | redeem2 = getRedeemSample2();
22 | assertThat(redeem1).isNotEqualTo(redeem2);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/RedeemTestSamples.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import java.util.UUID;
4 |
5 | public class RedeemTestSamples {
6 |
7 | public static Redeem getRedeemSample1() {
8 | return new Redeem().id("id1").type("type1").author("author1").login("login1").amount("amount1").code("code1");
9 | }
10 |
11 | public static Redeem getRedeemSample2() {
12 | return new Redeem().id("id2").type("type2").author("author2").login("login2").amount("amount2").code("code2");
13 | }
14 |
15 | public static Redeem getRedeemRandomSampleGenerator() {
16 | return new Redeem()
17 | .id(UUID.randomUUID().toString())
18 | .type(UUID.randomUUID().toString())
19 | .author(UUID.randomUUID().toString())
20 | .login(UUID.randomUUID().toString())
21 | .amount(UUID.randomUUID().toString())
22 | .code(UUID.randomUUID().toString());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/TypeTest.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import static com.camenduru.web.domain.TypeTestSamples.*;
4 | import static org.assertj.core.api.Assertions.assertThat;
5 |
6 | import com.camenduru.web.web.rest.TestUtil;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class TypeTest {
10 |
11 | @Test
12 | void equalsVerifier() throws Exception {
13 | TestUtil.equalsVerifier(Type.class);
14 | Type type1 = getTypeSample1();
15 | Type type2 = new Type();
16 | assertThat(type1).isNotEqualTo(type2);
17 |
18 | type2.setId(type1.getId());
19 | assertThat(type1).isEqualTo(type2);
20 |
21 | type2 = getTypeSample2();
22 | assertThat(type1).isNotEqualTo(type2);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/domain/TypeTestSamples.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.domain;
2 |
3 | import java.util.UUID;
4 |
5 | public class TypeTestSamples {
6 |
7 | public static Type getTypeSample1() {
8 | return new Type().id("id1").type("type1").amount("amount1").schema("schema1").model("model1").title("title1").cooldown("cooldown1");
9 | }
10 |
11 | public static Type getTypeSample2() {
12 | return new Type().id("id2").type("type2").amount("amount2").schema("schema2").model("model2").title("title2").cooldown("cooldown2");
13 | }
14 |
15 | public static Type getTypeRandomSampleGenerator() {
16 | return new Type()
17 | .id(UUID.randomUUID().toString())
18 | .type(UUID.randomUUID().toString())
19 | .amount(UUID.randomUUID().toString())
20 | .schema(UUID.randomUUID().toString())
21 | .model(UUID.randomUUID().toString())
22 | .title(UUID.randomUUID().toString())
23 | .cooldown(UUID.randomUUID().toString());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/com/camenduru/web/web/rest/WithUnauthenticatedMockUser.java:
--------------------------------------------------------------------------------
1 | package com.camenduru.web.web.rest;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 | import org.springframework.security.core.context.SecurityContext;
8 | import org.springframework.security.core.context.SecurityContextHolder;
9 | import org.springframework.security.test.context.support.WithSecurityContext;
10 | import org.springframework.security.test.context.support.WithSecurityContextFactory;
11 |
12 | @Target({ ElementType.METHOD, ElementType.TYPE })
13 | @Retention(RetentionPolicy.RUNTIME)
14 | @WithSecurityContext(factory = WithUnauthenticatedMockUser.Factory.class)
15 | public @interface WithUnauthenticatedMockUser {
16 | class Factory implements WithSecurityContextFactory {
17 |
18 | @Override
19 | public SecurityContext createSecurityContext(WithUnauthenticatedMockUser annotation) {
20 | return SecurityContextHolder.createEmptyContext();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "plugins": ["cypress", "@typescript-eslint"],
5 | "env": {
6 | "cypress/globals": true
7 | },
8 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:cypress/recommended"],
9 | "rules": {
10 | "@typescript-eslint/no-namespace": ["error", { "allowDeclarations": true }],
11 | "@typescript-eslint/no-unused-vars": "off"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/e2e/lighthouse.audits.ts:
--------------------------------------------------------------------------------
1 | describe('Lighthouse Audits', () => {
2 | beforeEach(() => {
3 | cy.visit('/');
4 | });
5 |
6 | it('homepage', () => {
7 | const customThresholds = {
8 | performance: 80,
9 | accessibility: 90,
10 | seo: 90,
11 | 'best-practices': 90,
12 | // If you have enabled PWA you should set this threshold to 100
13 | pwa: 0,
14 | };
15 |
16 | const desktopConfig = {
17 | extends: 'lighthouse:default',
18 | formFactor: 'desktop',
19 | // Change the CPU slowdown multiplier to emulate different kind of devices
20 | // See https://github.com/GoogleChrome/lighthouse/blob/master/docs/throttling.md#cpu-throttling for details
21 | throttling: {
22 | cpuSlowdownMultiplier: 1,
23 | },
24 | screenEmulation: { disabled: true },
25 | };
26 | cy.lighthouse(customThresholds, desktopConfig);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/fixtures/integration-test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/src/test/javascript/cypress/fixtures/integration-test.png
--------------------------------------------------------------------------------
/src/test/javascript/cypress/plugins/global.d.ts:
--------------------------------------------------------------------------------
1 | // workaround missing typings https://github.com/cypress-io/code-coverage/issues/257
2 | declare module '@cypress/code-coverage/task' {
3 | export default function codecov(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions): void;
4 | }
5 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/support/account.ts:
--------------------------------------------------------------------------------
1 | export type Account = Record;
2 |
3 | Cypress.Commands.add('getAccount', () => {
4 | return cy
5 | .authenticatedRequest({
6 | method: 'GET',
7 | url: '/api/account',
8 | })
9 | .then(response => response.body as Account);
10 | });
11 |
12 | Cypress.Commands.add('saveAccount', (account: Account) => {
13 | return cy.authenticatedRequest({
14 | method: 'POST',
15 | url: '/api/account',
16 | body: account,
17 | });
18 | });
19 |
20 | declare global {
21 | namespace Cypress {
22 | interface Chainable {
23 | getAccount(): Cypress.Chainable;
24 | saveAccount(account: Account): Cypress.Chainable>;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/support/index.ts:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 | import '@cypress/code-coverage/support';
16 |
17 | import './account';
18 | import './commands';
19 | import './navbar';
20 | import './entity';
21 | import './management';
22 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/support/management.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-namespace */
2 | /* eslint-disable @typescript-eslint/no-use-before-define */
3 |
4 | Cypress.Commands.add('getManagementInfo', () => {
5 | return cy
6 | .request({
7 | method: 'GET',
8 | url: '/management/info',
9 | })
10 | .then(response => response.body);
11 | });
12 |
13 | declare global {
14 | namespace Cypress {
15 | interface Chainable {
16 | getManagementInfo(): Cypress.Chainable;
17 | }
18 | }
19 | }
20 |
21 | // Convert this to a module instead of script (allows import/export)
22 | export {};
23 |
--------------------------------------------------------------------------------
/src/test/javascript/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../../../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "sourceMap": false,
6 | "outDir": "../../../../target/cypress/tsc",
7 | "target": "es2018",
8 | "types": ["cypress", "node"]
9 | },
10 | "include": ["./../../../../cypress*.config.ts", "./**/*.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/src/test/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.test.context.ContextCustomizerFactory = com.camenduru.web.\
2 | config.TestContainersSpringContextCustomizerFactory
--------------------------------------------------------------------------------
/src/test/resources/i18n/messages_en.properties:
--------------------------------------------------------------------------------
1 | email.test.title=test title
2 | # Value used for English locale unit test in MailServiceIT
3 | # as this file is loaded instead of real file
4 | email.activation.title=web account activation
5 |
--------------------------------------------------------------------------------
/src/test/resources/junit-platform.properties:
--------------------------------------------------------------------------------
1 | junit.jupiter.execution.timeout.default = 15 s
2 | junit.jupiter.execution.timeout.testable.method.default = 15 s
3 | junit.jupiter.execution.timeout.beforeall.method.default = 60 s
4 | junit.jupiter.testclass.order.default=com.camenduru.web.config.SpringBootTestClassOrderer
5 |
--------------------------------------------------------------------------------
/src/test/resources/templates/mail/activationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster activation
5 |
6 |
7 |
8 | Dear
9 | Your JHipster account has been created, please click on the URL below to activate it:
10 |
11 | Activation link
12 |
13 |
14 | Regards,
15 |
16 | JHipster.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/resources/templates/mail/creationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster creation
5 |
6 |
7 |
8 | Dear
9 | Your JHipster account has been created, please click on the URL below to access it:
10 |
11 | Login link
12 |
13 |
14 | Regards,
15 |
16 | JHipster.
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/resources/templates/mail/passwordResetEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster password reset
5 |
6 |
7 |
8 | Dear
9 |
10 | For your JHipster account a password reset was requested, please click on the URL below to reset it:
11 |
12 |
13 | Login link
14 |
15 |
16 | Regards,
17 |
18 | JHipster.
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/templates/mail/testEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./target/out-tsc/app",
5 | "types": ["@angular/localize"]
6 | },
7 | "files": ["src/main/webapp/sockjs-client.polyfill.ts", "src/main/webapp/main.ts"],
8 | "include": ["src/main/webapp/**/*.d.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src/main/webapp/",
4 | "outDir": "./target/out-tsc/root",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "strictNullChecks": true,
8 | "noImplicitReturns": true,
9 | "noFallthroughCasesInSwitch": true,
10 | "sourceMap": true,
11 | "declaration": false,
12 | "downlevelIteration": true,
13 | "experimentalDecorators": true,
14 | "moduleResolution": "node",
15 | "importHelpers": true,
16 | "esModuleInterop": true,
17 | "allowSyntheticDefaultImports": true,
18 | "useDefineForClassFields": false,
19 | "target": "es2022",
20 | "module": "es2020",
21 | "types": [],
22 | "lib": ["es2018", "es2020", "dom"]
23 | },
24 | "references": [
25 | {
26 | "path": "tsconfig.spec.json"
27 | }
28 | ],
29 | "angularCompilerOptions": {
30 | "strictInjectionParameters": true,
31 | "strictInputAccessModifiers": true,
32 | "strictTemplates": true,
33 | "preserveWhitespaces": true
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src/main/webapp/**/*.ts"],
4 | "compilerOptions": {
5 | "composite": true,
6 | "outDir": "target/out-tsc/spec",
7 | "types": ["jest", "node"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/webpack/environment.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | I18N_HASH: 'generated_hash',
3 | SERVER_API_URL: '',
4 | __VERSION__: process.env.hasOwnProperty('APP_VERSION') ? process.env.APP_VERSION : 'DEV',
5 | __DEBUG_INFO_ENABLED__: false,
6 | };
7 |
--------------------------------------------------------------------------------
/webpack/logo-jhipster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/camenduru/web/bab4f7ee8bdc6592ed11e1d966351e7fabdd62f7/webpack/logo-jhipster.png
--------------------------------------------------------------------------------
/webpack/proxy.conf.js:
--------------------------------------------------------------------------------
1 | function setupProxy({ tls }) {
2 | const serverResources = ['/api', '/services', '/management', '/v3/api-docs', '/h2-console', '/health'];
3 | const conf = [
4 | {
5 | context: serverResources,
6 | target: `http${tls ? 's' : ''}://localhost:8080`,
7 | secure: false,
8 | changeOrigin: tls,
9 | },
10 | {
11 | context: ['/websocket'],
12 | target: 'ws://127.0.0.1:8080',
13 | ws: true,
14 | },
15 | ];
16 | return conf;
17 | }
18 |
19 | module.exports = setupProxy;
20 |
--------------------------------------------------------------------------------