Skip to content

Commit 104d4ce

Browse files
committed
Add project files.
1 parent 90cf6e9 commit 104d4ce

File tree

111 files changed

+20607
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+20607
-0
lines changed

GhostUI/ClientApp/api/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { AuthApi } from './services/auth.service';
2+
export { SampleApi } from './services/sample.service';
3+
export { SignalRApi } from './services/signalR.service';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { BaseService } from './base.service';
2+
import { authService } from '../../config/constants';
3+
import { Credentials, AuthUser } from '../../store/modules/auth/types';
4+
5+
/**
6+
* Auth API abstraction layer communication via Axios (typescript singleton pattern)
7+
*/
8+
class AuthService extends BaseService {
9+
private static _authService: AuthService;
10+
11+
public static get Instance(): AuthService {
12+
return this._authService || (this._authService = new this(authService.CONTROLLER_ID));
13+
}
14+
15+
private constructor(controllerName: string) {
16+
super(controllerName);
17+
}
18+
19+
public async login(credentials: Credentials): Promise<AuthUser> {
20+
const { data } = await this.$http.post(authService.LOGIN_RQ, credentials);
21+
return <AuthUser> data;
22+
}
23+
24+
public async logout(): Promise<any> {
25+
const { data } = await this.$http.post(authService.LOGOUT_RQ);
26+
return data;
27+
}
28+
}
29+
30+
export const AuthApi = AuthService.Instance;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import axios, { AxiosInstance } from 'axios';
2+
import { handleError } from '../../utils/error-handler';
3+
4+
/**
5+
* Service API base class - configures default settings/error handling for inheriting class
6+
*/
7+
export abstract class BaseService {
8+
protected readonly $http: AxiosInstance;
9+
10+
protected constructor(controllerName: string, useInterceptors: boolean = true) {
11+
this.$http = axios.create({
12+
timeout: 50000,
13+
baseURL: `api/${controllerName}/`
14+
});
15+
16+
if (useInterceptors) {
17+
this.addResponseInterceptors();
18+
}
19+
}
20+
21+
private addResponseInterceptors(): void {
22+
this.$http.interceptors.response.use(
23+
(response) => {
24+
return response;
25+
},
26+
(error) => {
27+
handleError(error);
28+
return Promise.reject(error);
29+
}
30+
);
31+
}
32+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { BaseService } from './base.service';
2+
import { sampleService } from '../../config/constants';
3+
import { WeatherForecast } from '../../store/modules/weather-forecasts/types';
4+
5+
/**
6+
* SampleData API abstraction layer communication via Axios (typescript singleton pattern)
7+
*/
8+
class SampleService extends BaseService {
9+
private static _sampleService: SampleService;
10+
11+
public static get Instance(): SampleService {
12+
return this._sampleService || (this._sampleService = new this(sampleService.CONTROLLER_ID));
13+
}
14+
15+
private constructor(controllerName: string) {
16+
super(controllerName);
17+
}
18+
19+
public async getWeatherForecastsAsync(startDateIndex: number): Promise<WeatherForecast[]> {
20+
const { data } = await this.$http.get(sampleService.GET_FORECASTS_RQ, { params: { startDateIndex: startDateIndex } });
21+
return <WeatherForecast[]> data;
22+
}
23+
}
24+
25+
export const SampleApi = SampleService.Instance;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { EventBus } from '../../event-bus';
2+
import { signalrService } from '../../config/constants';
3+
import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@aspnet/signalr';
4+
5+
/**
6+
* SignalR API abstraction layer communication - configures/manages hub connections
7+
*/
8+
class SignalRService {
9+
private _hubConnection: HubConnection;
10+
private static _signalRService: SignalRService;
11+
12+
public static get Instance(): SignalRService {
13+
return this._signalRService || (this._signalRService = new this());
14+
}
15+
16+
private constructor() {
17+
this.createConnection();
18+
this.registerOnServerEvents();
19+
}
20+
21+
public startConnection(): void {
22+
if (this._hubConnection.state === HubConnectionState.Connected)
23+
return;
24+
25+
setTimeout(() => {
26+
this._hubConnection.start().catch((error) => {
27+
console.error(error.toString());
28+
});
29+
}, signalrService.CONNECTION_DELAY);
30+
}
31+
32+
private createConnection(): void {
33+
this._hubConnection = new HubConnectionBuilder()
34+
.withUrl(signalrService.BASE_URL)
35+
.build();
36+
}
37+
38+
private registerOnServerEvents(): void {
39+
this._hubConnection.on(signalrService.LOGIN_USER_EVENT, () => {
40+
setTimeout(() => {
41+
EventBus.$snotify.info('A user has logged in', signalrService.HUB_MESSAGE_TITLE);
42+
}, signalrService.HUB_MESSAGE_DELAY);
43+
});
44+
45+
this._hubConnection.on(signalrService.LOGOUT_USER_EVENT, () => {
46+
setTimeout(() => {
47+
EventBus.$snotify.info('A user has logged out', signalrService.HUB_MESSAGE_TITLE);
48+
}, signalrService.HUB_MESSAGE_DELAY);
49+
});
50+
51+
this._hubConnection.on(signalrService.CLOSE_EVENT, (reason: string) => {
52+
this._hubConnection.stop().then(() => {
53+
setTimeout(() => {
54+
EventBus.$snotify.info(`Hub closed (${reason})`, signalrService.HUB_MESSAGE_TITLE);
55+
}, signalrService.HUB_MESSAGE_DELAY);
56+
});
57+
});
58+
}
59+
}
60+
61+
export const SignalRApi = SignalRService.Instance;
Loading
Loading
Loading
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
.remember-me-control {
2+
text-align: center;
3+
}
4+
5+
.menu-list-control {
6+
display: block;
7+
padding: 0.55em 0.75em;
8+
}
9+
10+
.checkbox-control {
11+
margin-bottom: 1rem;
12+
13+
&.is-medium {
14+
font-size: 1.25rem;
15+
height: 2.25rem;
16+
}
17+
18+
&.menu-list-control {
19+
margin-bottom: inherit;
20+
}
21+
}
22+
23+
.remember-me-control .checkbox-control {
24+
line-height: 0.85;
25+
font-size: 1.15rem;
26+
font-weight: 400;
27+
}
28+
29+
.checkbox-control {
30+
&:not(.disabled) label:hover .helper {
31+
color: $color-checkbox-border-hover;
32+
}
33+
34+
input {
35+
opacity: 0;
36+
width: 1rem;
37+
height: 1rem;
38+
position: absolute;
39+
}
40+
41+
&.is-medium input {
42+
opacity: 0;
43+
left: 0;
44+
margin-top: 0.3rem;
45+
width: 1.25rem;
46+
height: 1.25rem;
47+
position: absolute;
48+
}
49+
}
50+
51+
input[type="checkbox"] {
52+
vertical-align: baseline;
53+
}
54+
55+
.checkbox-control {
56+
label {
57+
cursor: pointer;
58+
color: #4a4a4a;
59+
position: relative;
60+
display: block;
61+
62+
span {
63+
padding-left: 1.4em;
64+
}
65+
}
66+
67+
&.disabled {
68+
label {
69+
cursor: not-allowed;
70+
}
71+
72+
.helper {
73+
opacity: .7;
74+
}
75+
}
76+
77+
&.is-medium label span, &.menu-list-control span {
78+
padding-left: 1.75em;
79+
}
80+
81+
.helper {
82+
color: $color-checkbox-border;
83+
background-color: white;
84+
position: absolute;
85+
top: 0;
86+
width: 1rem;
87+
height: 1rem;
88+
z-index: 0;
89+
border: 0.125rem solid currentColor;
90+
border-radius: 0.0625rem;
91+
-webkit-transition: border-color 0.38s ease;
92+
transition: border-color 0.38s ease;
93+
}
94+
95+
&.menu-list-control .helper {
96+
top: 0.25rem;
97+
}
98+
99+
&.is-medium .helper {
100+
width: 1.25rem;
101+
height: 1.25rem;
102+
top: inherit;
103+
margin-top: 0.3rem;
104+
}
105+
106+
input:checked ~ .helper::before {
107+
height: 1.2rem;
108+
-webkit-transition-delay: 0.38s;
109+
transition-delay: 0.38s;
110+
}
111+
112+
&.is-medium input:checked ~ .helper::before {
113+
height: 1.5rem;
114+
}
115+
116+
input:checked ~ .helper {
117+
&::after, &::before {
118+
opacity: 1;
119+
-webkit-transition: height 0.38s ease;
120+
transition: height 0.38s ease;
121+
-webkit-transition-delay: 0s;
122+
transition-delay: 0s;
123+
}
124+
}
125+
126+
.helper::before {
127+
top: 0.65rem;
128+
left: 0.38rem;
129+
-webkit-transform: rotate(-135deg);
130+
transform: rotate(-135deg);
131+
}
132+
133+
&.is-medium .helper::before {
134+
top: 0.8125rem;
135+
left: 0.475rem;
136+
}
137+
138+
.helper {
139+
&::before, &::after {
140+
position: absolute;
141+
height: 0;
142+
width: 0.2rem;
143+
background-color: $color-checkbox-mark;
144+
display: block;
145+
transform-origin: left top;
146+
border-radius: 0.25rem;
147+
content: "";
148+
-webkit-transition: opacity 0.38s ease, height 0s linear 0.38s;
149+
transition: opacity 0.38s ease, height 0s linear 0.38s;
150+
opacity: 0;
151+
}
152+
}
153+
154+
&.is-medium .helper {
155+
&::before, &::after {
156+
width: 0.23rem;
157+
}
158+
}
159+
160+
input:checked ~ .helper::after {
161+
height: 0.5rem;
162+
}
163+
164+
&.is-medium input:checked ~ .helper::after {
165+
height: 0.625rem;
166+
}
167+
168+
.helper::after {
169+
top: 0.3rem;
170+
left: 0;
171+
-webkit-transform: rotate(-45deg);
172+
transform: rotate(-45deg);
173+
}
174+
175+
&.is-medium .helper::after {
176+
top: 0.375rem;
177+
}
178+
}

0 commit comments

Comments
 (0)