Compare commits

..

597 Commits

Author SHA1 Message Date
c93165ab13 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-11-28 00:46:11 +00:00
e3b656e8a9 회원수정 passowrd 처리 2022-11-28 00:46:08 +00:00
8e44497a08 version up of npm 2022-11-16 13:53:14 +00:00
13d65a58bf password 처리 2022-10-07 04:27:55 +00:00
139cd5e001 bug fix 2022-10-06 06:47:15 +00:00
0bc0edb91b password 처리 2022-10-05 09:32:24 +00:00
Park Byung Eun
f3bb24a4a8 보유금 수정 2022-09-18 07:49:16 +00:00
Park Byung Eun
7e11c3f87a 보유금 수정 2022-09-18 07:32:30 +00:00
Park Byung Eun
bb5a1ac3c2 파트너 리스트 수정 2022-09-18 03:22:40 +00:00
Park Byung Eun
6a5122a378 하부회원수 수정 2022-09-17 12:54:07 +00:00
3b637282f3 총 회원수 적용 2022-09-17 11:48:25 +00:00
Park Byung Eun
e2ff707637 매장수 적용 2022-09-17 10:39:50 +00:00
efa63afcd3 member_balance is added 2022-09-16 14:08:14 +00:00
9623974781 member model is modified 2022-09-16 10:28:21 +00:00
Park Byung Eun
7ccfe0e4f2 bug fix 2022-09-15 02:10:39 +00:00
Park Byung Eun
dd50a301c3 회원 상태, 레벨 수정 2022-09-14 08:42:06 +00:00
Park Byung Eun
1f875b708e bug fix 2022-09-14 05:35:00 +00:00
Park Byung Eun
5fd7d2f6f2 bug fix 2022-09-14 04:39:43 +00:00
Park Byung Eun
e104718a10 bugfix 2022-09-14 04:39:13 +00:00
Park Byung Eun
da5188c3bf bug fix 2022-09-14 04:27:21 +00:00
Park Byung Eun
15457adeda 정규표현식 추가 2022-09-14 03:18:11 +00:00
Park Byung Eun
2568703062 로그인 수정 2022-09-13 08:35:41 +00:00
Park Byung Eun
c10a628817 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-09-07 15:23:28 +00:00
Park Byung Eun
bbc896a3a9 bug fix 2022-09-07 15:23:21 +00:00
54aea119d9 modified 2022-09-07 03:25:19 +00:00
e7ae83912a member model is modified 2022-09-06 12:40:35 +00:00
cb39f9014c model is modified 2022-09-05 14:32:55 +00:00
ee54533547 Search 버튼 위치 수정 2022-09-05 12:37:51 +00:00
78302f355e 페이지 수정 2022-09-05 07:52:16 +00:00
114b5b9977 버튼수정 2022-09-04 07:08:29 +00:00
6494fece01 버튼 수정 2022-09-04 06:38:28 +00:00
c75347da04 파트너 입출금 정산 수정 2022-09-04 05:45:02 +00:00
Park Byung Eun
aa234ff124 슬롯 베팅 리스트 수정 2022-09-02 07:38:24 +00:00
Park Byung Eun
84642b8139 bug fix 2022-09-02 06:16:09 +00:00
Park Byung Eun
30fc6c3afa 배팅 리스트 롤링 수정 2022-09-02 06:09:40 +00:00
c555761b8c totoal_count is applied 2022-09-01 18:12:10 +00:00
144e5a0ad8 models are modified 2022-09-01 16:48:30 +00:00
bd76e7f253 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-09-01 10:33:08 +00:00
6720f80f33 model is modified 2022-09-01 10:33:05 +00:00
9f6abf5635 버튼수정 2022-09-01 09:19:42 +00:00
Park Byung Eun
b836bbf555 bug fix 2022-09-01 07:43:26 +00:00
Park Byung Eun
609b8eb81e betting-history 진행중 2022-09-01 07:35:17 +00:00
9b16bf5b34 model is changed 2022-09-01 03:23:13 +00:00
Park Byung Eun
628a663037 bug fix 2022-09-01 00:35:22 +00:00
909f18b2ca Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-31 14:18:05 +00:00
498e265e54 model is modified 2022-08-31 14:18:02 +00:00
cb9184648a 버튼 수정 2022-08-31 10:57:41 +00:00
c3c6da5e86 betting is added 2022-08-31 08:40:55 +00:00
Park Byung Eun
2148c97fb9 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-31 08:19:33 +00:00
Park Byung Eun
57a65e17fe 웹 입출금내역 화면 수정 2022-08-31 08:19:27 +00:00
958bc71a3a 아이콘 수정 2022-08-31 07:20:45 +00:00
a3eee13fbc 파트너 아이콘 수정 2022-08-31 06:36:51 +00:00
Park Byung Eun
4813572232 bug fix 2022-08-31 05:59:25 +00:00
Park Byung Eun
8d0e844c0b bug fix 2022-08-31 05:01:26 +00:00
Park Byung Eun
63ee6c23b2 충전내역 연동 완료 2022-08-31 04:58:58 +00:00
Park Byung Eun
bd7a3fc739 bug fix 2022-08-31 03:30:15 +00:00
Park Byung Eun
5838b6d7c5 bug fix 2022-08-31 02:08:42 +00:00
1a3201d231 사이드메뉴 아이콘수정 2022-08-30 15:02:40 +00:00
45bb511a4b constants are added 2022-08-30 10:44:12 +00:00
f0c418a658 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-30 10:24:38 +00:00
a36b7b87cf bug fixed 2022-08-30 10:24:35 +00:00
Park Byung Eun
8b52584b6e Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-30 09:30:03 +00:00
Park Byung Eun
5601844055 bug fix 2022-08-30 09:29:56 +00:00
55315ee131 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-30 08:35:41 +00:00
9dba95a7be bug fixed 2022-08-30 08:35:39 +00:00
Park Byung Eun
4007da31a2 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-30 08:18:03 +00:00
Park Byung Eun
c93a972425 bug fix 2022-08-30 08:17:58 +00:00
8bfc595d63 data type of money is changed 2022-08-30 07:53:27 +00:00
Park Byung Eun
950f0b5835 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-29 09:12:25 +00:00
Park Byung Eun
8afd2726e1 bug fix 2022-08-29 09:12:19 +00:00
733cb84af6 사용자 내역 테이블 2022-08-29 08:53:08 +00:00
Park Byung Eun
1265cb7213 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-29 08:36:23 +00:00
Park Byung Eun
7a73d7faa0 bug fix 2022-08-29 08:36:18 +00:00
459bc67020 proto is modified 2022-08-29 08:14:29 +00:00
Park Byung Eun
390ca7e24d bug fix 2022-08-29 05:35:19 +00:00
Park Byung Eun
388a036742 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-29 05:18:20 +00:00
Park Byung Eun
50827d9a67 bug fix 2022-08-29 05:18:13 +00:00
e5ac7d7661 name is changed 2022-08-29 04:12:17 +00:00
Park Byung Eun
d9c39cbb7b bug fix 2022-08-29 02:30:22 +00:00
b1b5b6f7fb error message is modified 2022-08-28 15:43:49 +00:00
d91f42c614 return type is changed 2022-08-28 13:37:54 +00:00
690e0b1631 입금관리 버튼 숨김 2022-08-28 11:37:32 +00:00
Park Byung Eun
6d4ab2bb43 bug fix 2022-08-28 08:47:53 +00:00
Park Byung Eun
62278134f6 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-28 08:18:22 +00:00
Park Byung Eun
dd4a871a4c 입금 관리 화면 수정 2022-08-28 08:18:17 +00:00
907a52ccb5 레벨변경버튼 수정 2022-08-27 14:29:18 +00:00
b63dd4f5be Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-27 06:39:16 +00:00
cd49c42b7c member_session is removed 2022-08-27 06:39:13 +00:00
4cbf901edd 레벨설정 버튼 2022-08-27 06:29:39 +00:00
Park Byung Eun
f20682f2be 게임설정 수정 완료 2022-08-26 06:43:18 +00:00
Park Byung Eun
c0e1345eec bug fix 2022-08-26 06:30:33 +00:00
Park Byung Eun
33c6cc553e 정산설정 수정 완료 2022-08-26 06:22:29 +00:00
Park Byung Eun
85f53c5d7d bug fix 2022-08-25 10:25:24 +00:00
Park Byung Eun
698cb9711f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 10:22:35 +00:00
Park Byung Eun
d5e7199699 충전내역 테이블 2022-08-25 10:22:30 +00:00
11e33e97b7 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 09:41:58 +00:00
bb6b3cfc85 bug fixed 2022-08-25 09:41:55 +00:00
Park Byung Eun
69fa77baef 사용자 내역 파일 추가 2022-08-25 09:40:16 +00:00
Park Byung Eun
42c02fcd56 member-settlement, member-game create resolver 2022-08-25 08:37:51 +00:00
Park Byung Eun
15dacd7b52 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 07:15:55 +00:00
Park Byung Eun
9762e257e8 site.resolver 위치 변경 2022-08-25 07:15:50 +00:00
28142c3da7 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 06:32:37 +00:00
57991d1981 bug fixed 2022-08-25 06:32:34 +00:00
Park Byung Eun
3b71dd1fe3 bug fix 2022-08-25 06:30:48 +00:00
Park Byung Eun
60f7417cdf Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 06:06:56 +00:00
Park Byung Eun
41dc0c9452 계좌정보 수정 2022-08-25 06:00:24 +00:00
14c94ff353 refactoring 2022-08-25 05:47:27 +00:00
d8d79fa2ba Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-25 05:46:55 +00:00
57a6dbc291 bug fixed 2022-08-25 05:40:06 +00:00
Park Byung Eun
fcfae3d496 bug fix 2022-08-25 03:15:12 +00:00
Park Byung Eun
f49e8a1fb7 bug fix 2022-08-24 12:42:43 +00:00
9a7eaba5fc bug fixed 2022-08-24 12:31:08 +00:00
Park Byung Eun
a4e498e22b Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-24 09:43:20 +00:00
Park Byung Eun
0f55e309ee 회원 수정 2022-08-24 09:43:15 +00:00
e453a7ba7e ux is changed 2022-08-24 08:56:38 +00:00
Park Byung Eun
7ce5df45be Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-24 06:33:24 +00:00
Park Byung Eun
8724c0468e 회원 리스트 수정 2022-08-24 06:33:19 +00:00
f0c8230f8e member, member_bank_account are modified 2022-08-24 05:58:58 +00:00
Park Byung Eun
39d9fc0f19 bug fix 2022-08-24 03:01:30 +00:00
Park Byung Eun
4980163e55 bug fix 2022-08-24 02:52:59 +00:00
Park Byung Eun
18a6593b31 회원수정 진행중 2022-08-24 02:40:18 +00:00
Park Byung Eun
31e3bc0943 bug fix 2022-08-23 09:58:04 +00:00
Park Byung Eun
93a3edec9d 사용자 상세화면 수정 2022-08-23 09:21:42 +00:00
Park Byung Eun
4d2656838a bug fix 2022-08-23 08:00:01 +00:00
Park Byung Eun
b3dfa69443 bug fix 2022-08-23 07:36:33 +00:00
Park Byung Eun
f888299684 bug fix 2022-08-23 07:22:59 +00:00
b7ae4f425a 페이지 수정 2022-08-23 06:24:07 +00:00
65e0a4fe4d expose service 2022-08-23 06:12:23 +00:00
82f8fef9e8 페이지 수정 2022-08-22 13:33:13 +00:00
236a54fbbb 페이지 수정 2022-08-22 13:05:40 +00:00
c0dbe4a4ce member_game_setting, member_settlement_setting are modified 2022-08-22 08:21:21 +00:00
88151b19ef member is modified 2022-08-22 08:05:06 +00:00
0870c7ed38 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-22 07:39:31 +00:00
d13f83b28c Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-22 07:02:02 +00:00
fedcf8108b member_game_setting, member_settlement_setting are added 2022-08-22 07:02:00 +00:00
e3817f6d73 페이지 수정 2022-08-22 06:58:50 +00:00
8255b443b5 페이지 수정 2022-08-22 06:56:43 +00:00
7188ee4d56 페이지 수정 2022-08-22 04:31:45 +00:00
1164796001 파트너전체목록 버튼추가 2022-08-22 04:10:05 +00:00
67791b4251 signinWithoutSecurityCode is added 2022-08-20 12:45:37 +00:00
e352e0c861 강제로그아웃 수정 2022-08-20 10:58:01 +00:00
aa2b2f6d6f 현재접속자 - 로그아웃버튼 2022-08-20 09:28:52 +00:00
644940de26 member_referrer is modified 2022-08-20 09:10:39 +00:00
c0548c1cb1 카지노 배팅리스트 수정 2022-08-20 08:25:33 +00:00
bbcae8f22f 안쓰는 모듈 정리 2022-08-20 07:30:30 +00:00
Park Byung Eun
e6a0c6e988 bug fix 2022-08-20 07:24:32 +00:00
3300c6d579 파워볼 삭제알림 2022-08-19 10:34:56 +00:00
6966e68804 공지사항 삭제알림 2022-08-19 10:30:29 +00:00
642160f8ad 팝업 알림 2022-08-19 10:25:15 +00:00
820f89d250 게임설정 알림 2022-08-19 10:21:56 +00:00
f0cf02bf47 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 10:16:17 +00:00
1c9b0b86b7 도메인삭제 알림 2022-08-19 10:16:14 +00:00
Park Byung Eun
6e19ca3520 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 10:13:02 +00:00
Park Byung Eun
f5b844f5da 진행중... 2022-08-19 10:12:56 +00:00
b3b4662b21 장기미접속회원-쪽지보내기 2022-08-19 08:44:43 +00:00
Park Byung Eun
3e6b61d8f1 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 08:41:51 +00:00
Park Byung Eun
6d7d23798b 추천인 등록 요청 2022-08-19 08:40:01 +00:00
c59a1b50de Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 08:36:12 +00:00
a018b473bc 추천인 추가/삭제 2022-08-19 08:36:09 +00:00
4cc31a17ab MemberReferrerService is added 2022-08-19 07:58:34 +00:00
e2f15292dd Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 07:44:44 +00:00
a4626f601f api for frontend is added 2022-08-19 07:44:41 +00:00
Park Byung Eun
515ae6f754 checkbox bug fix 2022-08-19 07:43:52 +00:00
0794156b86 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 06:56:01 +00:00
49399ae587 추천인 추가/ 삭제 다이얼로그 수정 2022-08-19 06:55:57 +00:00
dad2aaf7eb Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 06:55:31 +00:00
2ba57fe71c type of response is changed 2022-08-19 06:55:29 +00:00
8f3655fa24 현재접속자-배팅리스트 수정 2022-08-19 06:51:35 +00:00
12e95bc1f9 현재접속자 - 쪽지보내기 2022-08-19 06:40:12 +00:00
Park Byung Eun
f0510ed120 bug fix 2022-08-19 06:21:35 +00:00
Park Byung Eun
3e3e7c086a Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 06:20:07 +00:00
Park Byung Eun
fb36414fa0 추천코드등록 화면 수정 2022-08-19 06:10:15 +00:00
55359efa1b 입금관리 수정 2022-08-19 05:54:21 +00:00
3160d4d558 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-19 05:53:00 +00:00
b9f739f44e proto is changed 2022-08-19 05:52:56 +00:00
09be02ab52 추천인등록추가 다이얼로그 2022-08-19 05:39:24 +00:00
6d6f38c777 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-18 07:14:31 +00:00
4b87710878 list_vendors is added 2022-08-18 07:14:27 +00:00
Park Byung Eun
63038babf8 bug fix 2022-08-18 06:51:40 +00:00
Park Byung Eun
7a3cd8d530 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-18 06:42:16 +00:00
Park Byung Eun
227fb55c3d server ip added 2022-08-18 06:40:44 +00:00
72569d064f ip of development server is changed 2022-08-18 06:40:25 +00:00
Park Byung Eun
a9da20eb56 bug fix 2022-08-18 06:05:50 +00:00
Park Byung Eun
8250e68858 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-18 05:52:09 +00:00
Park Byung Eun
3adb1ae287 bug fix 2022-08-18 05:52:00 +00:00
ca2be7e6e2 오타수정 2022-08-18 03:54:22 +00:00
c1c9cb038c Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-18 03:39:57 +00:00
cea7d0152b vendor is added 2022-08-18 03:39:55 +00:00
Park Byung Eun
9fef46d48b Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-17 08:42:10 +00:00
26ce63d550 입금관리 리스트 완료 2022-08-17 07:51:30 +00:00
Park Byung Eun
91f29e4f32 bug fix 2022-08-17 06:23:10 +00:00
Park Byung Eun
7c89e9f1ab 출금관리 리스트 완료 2022-08-17 05:05:36 +00:00
Park Byung Eun
6bb671d3a5 bug fixed 2022-08-17 01:57:05 +00:00
18ab72488e user 수정 2022-08-16 05:04:48 +00:00
Park Byung Eun
b1d1889210 bug fix 2022-08-15 07:58:12 +00:00
Park Byung Eun
3eda379160 은행정보 출력 2022-08-15 07:10:30 +00:00
Park Byung Eun
02db4777a2 bug fixed 2022-08-15 06:44:26 +00:00
4860a698a5 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-15 04:34:12 +00:00
8a50bcf897 update_member is modified 2022-08-15 04:34:09 +00:00
Park Byung Eun
69139aebb9 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-15 04:21:21 +00:00
Park Byung Eun
ac773ecc30 현재 접속자 화면 수정 2022-08-15 04:21:15 +00:00
336ea311d9 member_bank_account is changed 2022-08-15 04:02:14 +00:00
0cde22e4f8 member is modified 2022-08-15 03:57:24 +00:00
Park Byung Eun
453cb9dcbf bug fixed 2022-08-15 02:29:43 +00:00
Park Byung Eun
3a560e2e0d 은행정보 등록 완료 2022-08-15 02:22:23 +00:00
87dbf53a2f id 클릭이벤트 2022-08-14 15:42:20 +00:00
13ef5f8280 create_member is modified
sample of bank account is added
2022-08-14 15:40:53 +00:00
64ab9ce51b create_member is modified 2022-08-14 15:19:59 +00:00
db4d900af4 요율 2022-08-14 12:51:23 +00:00
a1c0deeb8f 관리-배팅리스트 2022-08-14 12:43:15 +00:00
47b3333bad Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-14 12:28:39 +00:00
ea3c246c71 관리-배팅리스트 2022-08-14 12:28:36 +00:00
Park Byung Eun
3b7ef1a8fa bug fixed 2022-08-14 10:29:53 +00:00
77ad989391 list of partners is implemented 2022-08-14 09:45:27 +00:00
919db21162 bug fixed 2022-08-14 09:23:02 +00:00
2f39027610 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-14 08:54:53 +00:00
bfadb751c5 bug fixed 2022-08-14 08:54:50 +00:00
Park Byung Eun
9b6c62ad2e bug fix 2022-08-14 08:12:12 +00:00
Park Byung Eun
f57364bb4d bug fix 2022-08-14 07:22:58 +00:00
Park Byung Eun
ffda32c5e8 bug fix 2022-08-14 07:22:47 +00:00
Park Byung Eun
7172b4b9bf bug fixed 2022-08-14 04:25:20 +00:00
Park Byung Eun
c3e8b13e4f 회원 관리 팝업창 추가 2022-08-14 03:57:30 +00:00
Park Byung Eun
5cb66cf892 bug fix 2022-08-14 03:47:40 +00:00
3c943da2ef bug fixed 2022-08-13 20:17:59 +00:00
8c23c5a94d Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-13 20:15:52 +00:00
efdcec27bb refactoring 2022-08-13 20:15:48 +00:00
1fe0ed601f 관리-강제로그아웃 팝업생성 2022-08-13 05:11:50 +00:00
ed74addf5d 관리-쪽지보내기 팝업생성 2022-08-13 04:40:04 +00:00
922ed5377b 관리-쿠폰머니지급회수 팝업생성 2022-08-13 04:19:42 +00:00
a05c3c59e6 서버수정 2022-08-13 04:08:56 +00:00
c79a5dba20 서버 수정 2022-08-13 03:56:31 +00:00
a238b5bde7 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-13 03:54:07 +00:00
663296f0bc 관리-콤프지급회수 팝업생성 2022-08-13 03:54:02 +00:00
51958a34e1 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 09:40:46 +00:00
693d27555b bug fixed 2022-08-12 09:40:43 +00:00
Park Byung Eun
f9cf28023a Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 09:32:15 +00:00
Park Byung Eun
9bf22f83d3 회원 등록 연동 2022-08-12 09:28:56 +00:00
f0a850bbeb 오타수정 2022-08-12 09:25:34 +00:00
bc2f869bd9 관리-수수료설정 팝업생성 2022-08-12 09:23:10 +00:00
f52d6a1a6e bug fixed 2022-08-12 08:55:50 +00:00
bc4a78a1b5 protobuf is added 2022-08-12 08:45:27 +00:00
Park Byung Eun
a6a54e68e6 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 08:15:50 +00:00
aaf9664eed Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 08:15:32 +00:00
9ec9869826 bug fixed 2022-08-12 08:15:30 +00:00
Park Byung Eun
8b65a73c71 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 07:59:30 +00:00
Park Byung Eun
1f3f60f59f 진행중 2022-08-12 07:59:05 +00:00
27caf1469f 관리-보유금지급회수 팝업 생성 2022-08-12 07:56:00 +00:00
621899e348 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 07:41:37 +00:00
f841e1ad8b 진행중 2022-08-12 07:41:33 +00:00
Park Byung Eun
0c18d814b0 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-12 07:19:24 +00:00
Park Byung Eun
84ee61beea dialog bug fixed 2022-08-12 07:16:28 +00:00
26836d2405 bug fixed 2022-08-12 07:11:41 +00:00
9d8ae0eed2 bank is added 2022-08-12 06:44:39 +00:00
Park Byung Eun
79f2c4250c 회원수정 연동 2022-08-12 04:49:02 +00:00
Park Byung Eun
97bc9e256d Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-11 10:48:01 +00:00
Park Byung Eun
5ac8ae584d 사용자 조회 연동 2022-08-11 10:47:56 +00:00
006cf087c9 bug fixed 2022-08-11 08:33:35 +00:00
Park Byung Eun
afd51f5e3f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-11 08:18:57 +00:00
Park Byung Eun
3dd1902deb listMemberRequest 설정 2022-08-11 08:18:52 +00:00
51bcb290d4 actions of member are added 2022-08-11 08:17:37 +00:00
Park Byung Eun
0e07f16204 파트너 리스트 연동 2022-08-11 07:01:53 +00:00
90277b9b08 member list is added 2022-08-11 05:35:25 +00:00
19355220df Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-11 01:55:46 +00:00
9841dafef6 refactoring 2022-08-11 01:55:43 +00:00
Park Byung Eun
1d7a53359a Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-10 13:08:37 +00:00
Park Byung Eun
e0ff5847ff bug fixed 2022-08-10 13:08:31 +00:00
5d204258c8 오타수정 2022-08-10 12:06:51 +00:00
05e0dc3ec9 종목별매출통계 오타수정 2022-08-10 12:05:33 +00:00
4f0829e692 월현황 오타수정 2022-08-10 11:50:43 +00:00
c4d0a9b62f 루징관리 오타수정 2022-08-10 11:42:05 +00:00
8011ac9840 일일현황오타수정 2022-08-10 10:30:11 +00:00
e2ca4d403b 일일현황 오타수정 2022-08-10 10:29:38 +00:00
2eb6b29249 변수명수정 2022-08-10 10:07:24 +00:00
66cad9bb8e 출금관리 변수명수정 2022-08-10 09:58:22 +00:00
6cea6ab5cf 웹입출금정산 변수명수정 2022-08-10 09:31:28 +00:00
81769287dc 파트너입출금정산 변수명수정 2022-08-10 09:20:15 +00:00
ed056768b3 변수명수정 2022-08-10 09:03:02 +00:00
b6cbe8971a 변수명 수정 2022-08-10 08:08:17 +00:00
Park Byung Eun
a40e6b7a39 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-10 08:05:59 +00:00
Park Byung Eun
0b37894772 bug fixed 2022-08-10 08:05:53 +00:00
119ebac6ed MemberService is added 2022-08-10 08:05:23 +00:00
Park Byung Eun
a9fc35301d paging bug fixed 2022-08-10 06:52:38 +00:00
Park Byung Eun
152994e63b 닉네임 중복체크 2022-08-10 06:22:38 +00:00
Park Byung Eun
71876494d5 아이디 중복 체크 완료 2022-08-10 05:10:20 +00:00
06d8d250e0 site is changed 2022-08-10 02:36:13 +00:00
b395ef01b5 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-10 02:03:38 +00:00
84172273fc site is changed 2022-08-10 02:03:34 +00:00
Park Byung Eun
af143e6216 bug fix 2022-08-09 12:28:41 +00:00
Park Byung Eun
e11c423ba8 bug fix 2022-08-09 11:17:16 +00:00
Park Byung Eun
d8fa7066ad Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-09 10:15:41 +00:00
f0baebd107 site is added 2022-08-08 10:58:47 +00:00
Park Byung Eun
1d40b74f94 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 10:34:04 +00:00
Park Byung Eun
4630d9551c 진행중... 2022-08-08 10:34:00 +00:00
c2a2052998 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 10:17:09 +00:00
94ae77414d site is added 2022-08-08 10:17:06 +00:00
e15b7887cb Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 10:16:03 +00:00
21c0c3b34d 수정 2022-08-08 10:16:00 +00:00
Park Byung Eun
f169ba12bc Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 08:03:01 +00:00
Park Byung Eun
760402295f bug fix 2022-08-08 08:02:53 +00:00
87b7ec272f name is changed 2022-08-08 07:59:05 +00:00
92cfb9d0b7 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 07:51:11 +00:00
f310e5b15c refactoring 2022-08-08 07:51:08 +00:00
d70faa865f 변수명수정 2022-08-08 07:07:08 +00:00
53fa292fcf 변수명수정 2022-08-08 07:03:26 +00:00
65c185fa03 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 06:12:53 +00:00
812caa3a14 수정 2022-08-08 06:12:50 +00:00
080e597a76 success of signin is implemented 2022-08-08 02:55:11 +00:00
8eb085c3b4 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-08 02:12:48 +00:00
9ce4c7abf5 도메인 정렬 2022-08-08 02:12:44 +00:00
ba32c0dd6d rbac is added 2022-08-08 01:49:45 +00:00
ed64495059 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-07 07:45:15 +00:00
5924decae4 sessionId is added 2022-08-07 07:45:12 +00:00
8f57de6952 도메인 설정 page 추가 2022-08-06 11:15:09 +00:00
6fab831ef5 signin is modified 2022-08-06 05:49:39 +00:00
d2380e1e0a captcha is modified 2022-08-06 04:37:14 +00:00
891291af95 names are changed 2022-08-06 04:08:07 +00:00
Park Byung Eun
4d36bd6ae5 캡차코드 출력 2022-08-05 09:29:13 +00:00
Park Byung Eun
a512fe9b17 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-05 09:01:43 +00:00
Park Byung Eun
788f3d8b8f bug fix 2022-08-05 09:01:39 +00:00
eeb5424c47 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-05 08:58:44 +00:00
a2faa116c7 web-storage is added 2022-08-05 08:58:41 +00:00
Park Byung Eun
c91f56eeb6 modern page -> classic page 수정 2022-08-05 08:40:28 +00:00
Park Byung Eun
f98bb4653f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-05 07:50:24 +00:00
Park Byung Eun
938cc0a212 에볼루션 페이지 수정 2022-08-05 07:50:19 +00:00
d80ff7368a rpc is changed 2022-08-05 07:28:27 +00:00
b69c09f0c1 configuration of devcontainer is changed 2022-08-05 07:08:59 +00:00
05c8a5ddee data 추가 2022-08-05 06:15:18 +00:00
Park Byung Eun
4d9c4d3fed font size 수정 2022-08-05 03:43:15 +00:00
1af511114c bug fix 2022-08-04 13:23:03 +00:00
73f369ac42 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-04 11:50:11 +00:00
49c0c925c1 bug fix 2022-08-04 11:48:49 +00:00
Park Byung Eun
05a54fa16f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-04 11:47:07 +00:00
Park Byung Eun
0e218a9ef8 슬롯 베팅리스트 수정 2022-08-04 11:47:02 +00:00
c9a6fa01f7 폴더명 수정 2022-08-04 09:30:09 +00:00
f5de3d038c 폴더명 수정 2022-08-04 08:59:56 +00:00
ce51b9e44f 폴더명 수정 2022-08-04 08:40:45 +00:00
b5cf7173e7 보고서관리 수정 2022-08-04 07:15:38 +00:00
Park Byung Eun
0a91f62507 로그인 정보 수정 2022-08-04 07:05:33 +00:00
Park Byung Eun
bc26f5c3fe Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-04 06:29:48 +00:00
Park Byung Eun
b966b80563 중복로그인 리스트 수정 2022-08-04 06:29:42 +00:00
9baf91c5a2 종목별매출통계 2022-08-04 05:52:52 +00:00
Park Byung Eun
fc7fef6f8f bug fix 2022-08-04 05:12:36 +00:00
Park Byung Eun
44a0b7bc8a bug fix 2022-08-04 04:27:08 +00:00
Park Byung Eun
e761119454 bug fix 2022-08-04 04:10:33 +00:00
Park Byung Eun
b74000bde1 관리자로그인정보 진행중 2022-08-03 11:22:09 +00:00
Park Byung Eun
9055a4b209 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-03 10:47:09 +00:00
Park Byung Eun
bf0a7228fa 엑셀 다운로그 페이지 수정 2022-08-03 10:47:05 +00:00
6de12b35ff Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-03 10:46:20 +00:00
33838a3b90 server integration is implemented 2022-08-03 10:46:16 +00:00
Park Byung Eun
5aab6cd3a8 bug fix 2022-08-03 10:14:34 +00:00
Park Byung Eun
b9d10d3586 루징 리포터 페이지 추가 및 수정 2022-08-03 10:09:54 +00:00
Park Byung Eun
a629f3bd95 루징 관리 기본 데이터 뷰 진행중 2022-08-03 06:52:00 +00:00
Park Byung Eun
c7e45f48f0 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-02 09:54:14 +00:00
Park Byung Eun
edb24ef08d 루징 관리 기본 데이터 상세 진행중 2022-08-02 09:54:09 +00:00
b8a5b98d81 쿠폰발행머니로그 변수명수정 2022-08-02 09:32:31 +00:00
8d3f338c0d 수동지급회수로그 수정 2022-08-02 09:06:12 +00:00
Park Byung Eun
2f491e7207 bug fix 2022-08-02 08:25:11 +00:00
Park Byung Eun
787d0d8c74 루징 리스트 수정 2022-08-02 08:24:22 +00:00
Park Byung Eun
6298e601fa 루징 관리 리스트 수정 2022-08-02 06:55:07 +00:00
db7360aa17 머니활동로그 수정 2022-08-01 12:11:17 +00:00
e3db259a59 회원수정로그 수정 2022-08-01 12:05:43 +00:00
ef0509035a 수정 2022-08-01 11:06:05 +00:00
354e84dc86 콤프사용logs 수정 2022-08-01 11:05:00 +00:00
bb3a876fdf Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-01 10:02:20 +00:00
d20c5dd6d8 머니활동 로그 수정 2022-08-01 10:02:17 +00:00
Park Byung Eun
f503b86c73 공지사항 수정 2022-08-01 08:59:00 +00:00
Park Byung Eun
b4643ed501 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-01 08:03:37 +00:00
Park Byung Eun
cdd5586744 한줄공지 수정 2022-08-01 08:03:31 +00:00
abefe9721f 머니활동로그 수정 2022-08-01 06:52:19 +00:00
84d14dd7b7 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-08-01 05:34:00 +00:00
8572a5ea35 nats is added 2022-08-01 05:33:57 +00:00
6b726333dd 종목별매출통계 api수정 2022-08-01 05:20:25 +00:00
c00969fbb4 종목별매출통계 수정 2022-08-01 05:17:46 +00:00
Park Byung Eun
21188f3ca9 bug fix 2022-07-29 02:35:00 +00:00
Park Byung Eun
f9c31028ca Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-29 02:18:04 +00:00
Park Byung Eun
7fd616df0c 팝업 등록, 수정, 상세 페이지 추가 2022-07-29 02:17:59 +00:00
8dfd81dd11 금일배팅자목록 수정 2022-07-28 13:03:40 +00:00
571d6cea3a 버튼 수정 2022-07-28 01:16:25 +00:00
acf0cc361d Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-27 09:15:08 +00:00
d6705efef5 파트너 일일현황 수정 2022-07-27 09:15:03 +00:00
7c6da7b882 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-27 09:08:29 +00:00
f3471a8d93 protobuf is added 2022-07-27 09:08:25 +00:00
Park Byung Eun
b9b9514bb3 팝업 상세 및 수정 추가 2022-07-27 09:07:05 +00:00
Park Byung Eun
de413282b3 팝업창 테이블 수정 및 파일 정리 2022-07-27 07:03:56 +00:00
Park Byung Eun
ef7a54f030 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-26 10:13:01 +00:00
Park Byung Eun
fc94ec2aac 쪽지함 리스트 수정 2022-07-26 10:12:57 +00:00
d7746dd10c 월현황 수정 실패 2022-07-26 10:00:39 +00:00
Park Byung Eun
324cd51d73 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-26 09:19:54 +00:00
Park Byung Eun
c5420365e8 bug fix 2022-07-26 09:19:50 +00:00
ce357128a9 페이지 수정 2022-07-26 08:48:40 +00:00
Park Byung Eun
a5f5035357 bug fix 2022-07-26 08:41:10 +00:00
Park Byung Eun
72d7fc3895 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-26 08:40:02 +00:00
Park Byung Eun
d3c6f99041 고객센터 리스트 수정 2022-07-26 08:39:58 +00:00
c8bdcce0a6 현재접속자 수정 2022-07-26 08:35:42 +00:00
c6c8e5d792 현재접속자 수정 2022-07-26 08:21:18 +00:00
Park Byung Eun
5ad7b6ed80 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-26 07:06:05 +00:00
Park Byung Eun
cc794339a8 알림 컴포넌트 추가 2022-07-26 07:05:59 +00:00
fddd823277 파트너관리 라우팅 수정 2022-07-26 06:18:18 +00:00
1cfa17eb5b 일일현황 수정 2022-07-26 06:06:12 +00:00
Park Byung Eun
f9daaa7858 고객템플릿 등록, 수정 추가 2022-07-26 06:03:56 +00:00
53dd2e8c98 수정 2022-07-26 04:04:52 +00:00
b3a792506b 에볼루션배팅리스트 수정 2022-07-26 02:01:41 +00:00
12ff578d4c 카지노배팅리스트 수정 2022-07-25 13:22:54 +00:00
fc876fc5e1 리스트 디테일 수정 2022-07-25 09:09:05 +00:00
5b0d7641e5 버튼수정 2022-07-25 08:19:16 +00:00
a857a6735a 파워볼 수정 2022-07-25 08:14:21 +00:00
b5d9930616 selector 수정 2022-07-25 07:07:51 +00:00
677866f053 파트너 입출금정산 수정 2022-07-25 07:05:48 +00:00
71e4f7cff3 출금관리 수정 2022-07-25 06:28:34 +00:00
2006ef8f61 웹입출금정산 수정 2022-07-25 04:07:22 +00:00
605f0f5ef4 입금관리 수정 2022-07-25 02:36:06 +00:00
7c94200594 수정 2022-07-24 14:19:51 +00:00
b0e5604bec 쿠폰발행로그 수정 2022-07-24 13:57:45 +00:00
1d13797e55 쿠폰발행리스트 수정 2022-07-24 13:16:10 +00:00
3401a2dea1 쿠폰발행머니로그 수정 2022-07-24 13:07:36 +00:00
193a80847d 쿠폰발행리스트 수정 2022-07-24 10:33:54 +00:00
404c8820ac 추천코드 페이지 수정 2022-07-24 08:47:33 +00:00
51bda33071 수정 2022-07-24 08:44:41 +00:00
2a3603aa42 버튼추가 2022-07-24 08:33:10 +00:00
74afc90896 사이드메뉴-파트너관리 정리 2022-07-24 08:26:00 +00:00
b82b13bc30 추천코드등록페이지 수정 2022-07-24 07:17:37 +00:00
9d329d414a 파트너페이지 수정 2022-07-24 05:22:33 +00:00
78060e6bf8 전체파트너 수정 2022-07-22 04:58:29 +00:00
56048ddea4 수정 2022-07-22 03:28:46 +00:00
00bc20dd0c 현재접속자 쪽지전송 수정 2022-07-22 03:14:01 +00:00
758d25b0f1 카지노머니파악 수정 2022-07-22 01:58:06 +00:00
ccc3ed9d81 장기미접속회원 수정 2022-07-22 01:50:56 +00:00
40e567a349 회원리스트 수정 2022-07-22 01:36:49 +00:00
3c49c5eb72 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-22 01:08:42 +00:00
1d8d0743d8 vertical align is modifed 2022-07-22 01:08:39 +00:00
ff32f29aad list item is refined 2022-07-22 01:04:04 +00:00
7a94cecb1d list item is refined 2022-07-22 00:42:30 +00:00
Park Byung Eun
6778e3e8eb redit 컴포넌트 추가 2022-07-21 10:55:21 +00:00
Park Byung Eun
c845303bc6 등록버튼 추가 2022-07-21 10:08:07 +00:00
Park Byung Eun
6ddc2850d4 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-21 09:53:54 +00:00
Park Byung Eun
d653b61bf0 고객센터 템플릿 테이블 수정 2022-07-21 09:53:49 +00:00
900d1c5eed list item is refined 2022-07-21 09:47:43 +00:00
1d8c974f63 장기미접속회원리스트 수정 2022-07-21 09:34:20 +00:00
72c585b590 bet-mat-small-8 is added 2022-07-21 07:37:14 +00:00
d2abfc4254 list item is refined 2022-07-21 07:03:01 +00:00
f753247ea1 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-21 02:23:13 +00:00
d8c36058c0 @mdi/angular-material is added 2022-07-21 02:23:10 +00:00
b5d2ee3523 수정 2022-07-20 09:25:14 +00:00
58b2922d87 금일배팅자목록리스트 page 수정 2022-07-20 09:24:34 +00:00
e590aaa6f2 쿠폰발행머니로그 page 수정 2022-07-20 08:06:46 +00:00
fc5141c709 카지노머니파악 page 수정 2022-07-20 07:57:51 +00:00
Park Byung Eun
1ab80bd5a5 bug fix 2022-07-20 07:53:42 +00:00
Park Byung Eun
152ebe4895 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-20 07:45:46 +00:00
Park Byung Eun
1ba1c72f7f bug fix 2022-07-20 07:45:42 +00:00
bc2191ff05 금일배팅자목록리스트 page 수정 2022-07-20 07:38:58 +00:00
Park Byung Eun
f8dc320f21 bug fix 2022-07-20 07:28:22 +00:00
Park Byung Eun
eec65f477d bug fix 2022-07-20 07:16:51 +00:00
Park Byung Eun
e27884a07a bug fix 2022-07-20 07:10:54 +00:00
Park Byung Eun
0b95f6f6e8 bug fix 2022-07-18 09:53:53 +00:00
01cd0cdb8f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-18 09:43:55 +00:00
f8067b610e 고객센터리스트 page 수정 2022-07-18 09:43:53 +00:00
Park Byung Eun
bffa0d818c bug fix 2022-07-18 09:40:29 +00:00
Park Byung Eun
43a770a9d1 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-18 09:39:36 +00:00
Park Byung Eun
12826fb6b2 파트너일일현황 2022-07-18 09:39:30 +00:00
8e2f048db0 쪽지함리스트 page 수정 2022-07-17 06:48:50 +00:00
5a8b5939db 공지사항리스트 page 수정 2022-07-17 05:49:18 +00:00
d937a67453 팝업 리스트 page 수정 2022-07-17 05:45:46 +00:00
d377fc985f 오타수정 2022-07-17 05:07:02 +00:00
0f9d7148d9 bug fix 2022-07-17 05:00:07 +00:00
Park Byung Eun
cafcd1e838 메뉴 수정 2022-07-17 00:58:07 +00:00
182b7bd016 Revert "공지사항 리스트 page 수정"
This reverts commit 2ae4c91494.
2022-07-16 04:41:14 +00:00
ab645e42e2 한줄공지리스트 page 추가 2022-07-15 08:28:09 +00:00
Park Byung Eun
40ee141d0c Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-15 08:22:08 +00:00
Park Byung Eun
b34f2ebfff 파트너 등록 다이얼로그 추가 2022-07-15 08:22:02 +00:00
2ae4c91494 공지사항 리스트 page 수정 2022-07-15 07:59:11 +00:00
Park Byung Eun
fb21ccf389 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-15 07:11:57 +00:00
Park Byung Eun
0090cc5c65 파트너 폴더 정리 2022-07-15 07:11:51 +00:00
d92ec12e38 page 삭제 2022-07-15 06:32:06 +00:00
3a9d18c11c 머니활동로그-관리자&파트너지급회수 page 추가 2022-07-15 05:48:02 +00:00
d3070a0dba 콤프사용로그-관리자지급회수 page 추가 2022-07-15 05:41:27 +00:00
7f9beccc28 공지사항 상세 page 추가 2022-07-15 05:38:15 +00:00
0b6a91aadf 한줄공지 상세 page 추가 2022-07-15 05:36:59 +00:00
9c71427265 팝업 상세 page, 팝업 수정 page 추가 2022-07-15 05:32:54 +00:00
825f809245 쪽지함 상세 page 추가 2022-07-15 05:05:23 +00:00
214ef9482c 고객센터중복로그인 page 추가 2022-07-15 04:52:49 +00:00
879fa3ea75 고객센터템플릿 상세 page 오타수정 2022-07-15 04:50:24 +00:00
8eacb24d1a 고객센터 상세 page 추가 2022-07-15 04:48:42 +00:00
623dca08fc 고객센터템플릿 상세 page 추가 2022-07-15 04:45:11 +00:00
7a29769391 공지사항중복로그인 page 파일명 수정 2022-07-15 04:41:02 +00:00
3b537dfde4 공지사항 중복로그인 page 추가 2022-07-15 04:31:35 +00:00
aa3ff32913 팝업창만들기 page 추가 2022-07-15 03:32:00 +00:00
73d7ada50e 한줄공지 등록 page 추가 2022-07-15 03:29:41 +00:00
62f2557ced 공지사항 등록 page, 고객센터템플릿 등록 page 추가 2022-07-15 03:27:40 +00:00
4fc5f9f9f0 고객센터 page 수정 2022-07-14 18:17:04 +00:00
0f0063844f 고객센터템플릿 page 추가 2022-07-14 13:15:27 +00:00
581d94ae0e Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-14 09:19:59 +00:00
9273783a47 bug fix 2022-07-14 09:19:56 +00:00
Park Byung Eun
5189d7a2a3 bug fix 2022-07-14 09:19:48 +00:00
Park Byung Eun
82189ee93c bug fix 2022-07-14 09:15:31 +00:00
Park Byung Eun
071ff89ff3 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-14 09:13:11 +00:00
Park Byung Eun
4901930c11 게임ON/OFF 페이지 수정 2022-07-14 09:13:06 +00:00
eb19f24f55 파트너입출금정산 page 추가 2022-07-14 08:45:04 +00:00
2537d85937 웹입출금정산 page 추가 2022-07-14 08:29:59 +00:00
9cdf0a37b2 고객센터 page 추가 2022-07-14 08:03:04 +00:00
5f7f1989ee Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-14 07:45:18 +00:00
94ef4846f1 쪽지함 page 추가 2022-07-14 07:45:11 +00:00
Park Byung Eun
467c31ee5c Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-14 07:27:03 +00:00
Park Byung Eun
287a93d8d7 에보/대본 설정 페이지 화면 수정 2022-07-14 07:26:58 +00:00
7ea5effd46 팝업 page 추가 2022-07-14 07:20:33 +00:00
22a1e377c2 한줄공지 page 추가 2022-07-14 06:58:37 +00:00
82411255c7 공지사항 page 추가 2022-07-14 06:22:04 +00:00
Park Byung Eun
1c62f536b8 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-14 06:07:46 +00:00
Park Byung Eun
08b6c8721d 설정 페이지 추가 2022-07-14 06:07:40 +00:00
6ec39361d6 관리자로그인정보 page 추가 2022-07-14 05:45:55 +00:00
e2a7a45e76 중복로그인 page 추가 2022-07-14 05:25:53 +00:00
0de2b258b8 로그인정보 page 추가 2022-07-14 05:04:54 +00:00
0b7ed6a7e7 루징관리 page 추가 2022-07-14 02:48:44 +00:00
3b9b7246c4 엑셀다운로그 page 추가 2022-07-14 01:07:12 +00:00
e115110d95 수동지급회수로그 page 추가 2022-07-13 23:49:08 +00:00
e4ef8eec99 회원수정로그 page 추가 2022-07-13 23:28:04 +00:00
c7e2dc54f6 콤프사용로그 page 추가 2022-07-13 23:09:00 +00:00
d53bc384a7 머니활동로그 page 추가 2022-07-13 22:53:01 +00:00
431d21efff 종목별매출통계 page 추가 2022-07-13 22:13:21 +00:00
10d36349a1 금일배팅자목록 page 추가 2022-07-13 12:25:58 +00:00
1a8e2fcd31 파트너일일현황 page 추가 2022-07-13 11:34:11 +00:00
Park Byung Eun
20d3b021dd Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 11:18:19 +00:00
Park Byung Eun
c8b5293f7e 기본설정 수정 2022-07-13 11:18:14 +00:00
a7791e5049 bug fix 2022-07-13 10:59:19 +00:00
39510406be Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 10:59:04 +00:00
Park Byung Eun
34f87467b1 사이트 기본 설정 테이블 컬럼 추가 및 수정 2022-07-13 09:59:15 +00:00
631497a534 ing.. 2022-07-13 09:35:00 +00:00
Park Byung Eun
4826a71db2 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 09:25:24 +00:00
Park Byung Eun
d6c38a634c 기본설정 페이지 추가 2022-07-13 09:19:57 +00:00
0440325e67 월현황 page 추가 2022-07-13 09:16:31 +00:00
731ea28bd3 일일현황 page 추가 2022-07-13 08:45:52 +00:00
bc83da4bd9 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 08:02:48 +00:00
4631acb5a0 쿠폰발행로그 page 추가 2022-07-13 08:02:41 +00:00
Park Byung Eun
115fe9b8af Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 07:17:19 +00:00
Park Byung Eun
75c3333ae0 현재접속자 리스트 수정 2022-07-13 07:16:11 +00:00
3473e61f0b 쿠폰발행머니로그 page 추가 2022-07-13 06:47:59 +00:00
2994960b64 쿠폰발행 머니로그 page 추가 2022-07-13 06:46:57 +00:00
b13ffeea4e 쿠폰발행리스트 page 추가 2022-07-13 05:58:28 +00:00
b9735293af 추천코드등록 page 추가 2022-07-13 05:23:31 +00:00
08cf1f1f97 bug fix 2022-07-13 05:08:04 +00:00
23d666768c 파트너 매장 page 추가 2022-07-13 04:50:42 +00:00
Park Byung Eun
84c5c79985 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-13 02:47:14 +00:00
Park Byung Eun
ef7d282186 ing... 2022-07-13 02:47:08 +00:00
64eda57ac7 파트너 총판 page 추가 2022-07-13 02:28:19 +00:00
7734a4585e bug fix 2022-07-13 02:14:58 +00:00
3f559c1de5 파트너 본사 page 추가 2022-07-13 02:10:43 +00:00
d05227816a 파트너 부본 page 추가 2022-07-13 01:29:00 +00:00
2d8e2b02b4 fix 2022-07-13 00:57:16 +00:00
48af3a9a71 파일명변경 2022-07-13 00:54:15 +00:00
5fbcd6aa28 파트너 본사 page 추가 2022-07-12 13:32:33 +00:00
be39026b6a 전체파트너 page 추가 2022-07-12 06:05:24 +00:00
Park Byung Eun
39abd3aa29 bug fix 2022-07-11 08:37:28 +00:00
Park Byung Eun
849d8bb8b9 bug fix 2022-07-11 08:19:19 +00:00
Park Byung Eun
266e2e3593 bug fix 2022-07-11 05:53:25 +00:00
Park Byung Eun
b734e9594b bug fix 2022-07-11 05:21:34 +00:00
Park Byung Eun
3d35f3f39f Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-11 04:11:28 +00:00
834b3207d9 현재접속자 쪽지전송 page 추가 2022-07-09 11:56:11 +00:00
Park Byung Eun
bf8ee8245a bug fix 2022-07-08 08:35:46 +00:00
dded7ac3db 사용자페이지 에러 2022-07-08 06:51:30 +00:00
306f0c91c8 장기미접속회원 에러 2022-07-08 06:49:52 +00:00
349db9f616 사용자페이지 에러 2022-07-08 06:45:10 +00:00
90f28d604a 장기미접속회원 변수명 수정 2022-07-08 06:41:22 +00:00
bd63033710 카지노머니파악 변수명 수정 2022-07-08 06:25:40 +00:00
260b68139a 파워볼 변수명수정 2022-07-08 03:58:14 +00:00
5051514261 출금관리 변수명 수정 2022-07-08 03:56:35 +00:00
1112ee881c 카지노배팅리스트 변수명 수정 2022-07-08 03:53:52 +00:00
1931ea0dc1 입금관리, 파워볼, 사용자 변수명수정 2022-07-08 03:14:42 +00:00
6be23a1a12 출금관리에 회원상세보기 추가 2022-07-07 12:44:55 +00:00
3705407ee0 입금관리에 회원상세보기 추가 2022-07-07 12:41:46 +00:00
012b2be24c powerball에 회원상세보기 추가 2022-07-07 12:34:49 +00:00
bf1c18fea3 casinomoney페이지에 회원상세보기추가 2022-07-07 12:29:02 +00:00
9d042a73bf 장기미접속회원 page 추가 2022-07-07 12:19:24 +00:00
Park Byung Eun
0aa7a47aca Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-07 10:47:10 +00:00
Park Byung Eun
09a627e64b bug fix 2022-07-07 10:47:06 +00:00
a514b49e05 카지노머니파악 page 추가 2022-07-07 10:06:51 +00:00
4db7531aac 슬롯배팅리스트 page 추가 2022-07-07 08:02:23 +00:00
139c958c04 에볼루션배팅리스트 page 추가 2022-07-07 06:34:30 +00:00
6e4a007837 오타 수정 2022-07-07 05:14:48 +00:00
45a7baf55a 입금관리 오타 수정 2022-07-07 02:38:52 +00:00
374e98d0c2 출금관리 오타 수정 2022-07-07 02:34:43 +00:00
1426cb91bb 카지노배팅리스트 페이지 추가 2022-07-07 01:35:36 +00:00
Park Byung Eun
457bfae6da Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-06 10:02:41 +00:00
Park Byung Eun
af60a4a1fd grid added 2022-07-06 10:02:34 +00:00
e47f26146c Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-06 06:45:32 +00:00
5bd7dda4b3 파워볼 page 추가 2022-07-06 06:45:28 +00:00
Park Byung Eun
5ce6c4f656 user view route modify 2022-07-06 06:38:44 +00:00
Park Byung Eun
d09c29c051 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-06 05:50:38 +00:00
Park Byung Eun
48d19d0573 bug fix 2022-07-06 05:50:34 +00:00
4a8a4e6ee7 출금관리 리스트 수정 2022-07-06 01:46:05 +00:00
c68b5e394f 입금관리 리스트 수정 2022-07-06 01:44:15 +00:00
279c7e1bc0 회원리스트 수정 2022-07-05 13:53:11 +00:00
c57fa5df7a 출금관리 리스트 추가 2022-07-05 13:31:15 +00:00
16c5bff4a2 입금관리 리스트 추가 2022-07-05 08:38:41 +00:00
63c8663227 Merge branch 'feature/BETERAN-BACKEND-APP-BROWSER-init' of https://gitlab.loafle.net/bet/beteran-backend-app-browser into feature/BETERAN-BACKEND-APP-BROWSER-init 2022-07-04 12:31:24 +09:00
d572098e11 회원 리스트 추가 2022-07-04 12:30:42 +09:00
eb268381e2 회원리스트 page 추가 2022-07-04 12:04:42 +09:00
Park Byung Eun
4cf59daaa1 user view ing... 2022-07-01 07:47:26 +00:00
ec66700b1d initialized 2022-06-28 16:40:33 +09:00
1192 changed files with 279877 additions and 79 deletions

20
.browserslistrc Normal file
View File

@ -0,0 +1,20 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR

17
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,17 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.224.2/containers/typescript-node/.devcontainer/base.Dockerfile
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster
ARG VARIANT="16-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment if you want to install an additional version of node using nvm
# ARG EXTRA_NODE_VERSION=10
# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}"
# [Optional] Uncomment if you want to install more global node packages
# RUN su node -c "npm install -g <your-package-list -here>"
RUN su node -c "npm install -g npm@9.1.1"

View File

@ -0,0 +1,54 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.2/containers/typescript-node
{
"name": "beteran-backend-app-browser",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 16, 14, 12.
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"args": {
"VARIANT": "16-bullseye"
}
},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
// VS Code don't watch files under ./target
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/*/**": true
},
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"angular.ng-template",
"donjayamanne.githistory",
"eamodio.gitlens",
"mhutchie.git-graph"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
"portsAttributes": {
"4300": {
"label": "beteran-backend-app-browser",
"onAutoForward": "notify"
}
},
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
"postCreateCommand": "bash ./.devcontainer/scripts/postCreateCommand.sh",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}

View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -ex
npm install -g @angular/cli

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

79
.eslintrc.json Normal file
View File

@ -0,0 +1,79 @@
{
"root": true,
"env": {
"es6": true
},
"parserOptions": {
"ecmaVersion": 2018
},
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"parserOptions": {
"project": ["tsconfig.json"],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/ng-cli-compat",
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "",
"style": "camelCase"
}
],
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/naming-convention": [
{ "leadingUnderscore": "allowSingleOrDouble" }
],
"@typescript-eslint/no-inferrable-types": "off",
"arrow-parens": [
"error",
"as-needed",
{
"requireForBlockBody": true
}
],
"brace-style": ["off", "off"],
"import/order": "off",
"max-len": [
"error",
{
"ignorePattern": "^import |^export | implements",
"code": 180
}
],
"no-underscore-dangle": "off",
"object-shorthand": "off",
"quote-props": ["error", "consistent"],
"quotes": ["error", "single"]
}
},
{
"files": ["*.html"],
"extends": ["plugin:@angular-eslint/template/recommended"],
"rules": {}
}
]
}

46
.gitignore vendored Normal file
View File

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.angular/cache
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

1
.npmrc Normal file
View File

@ -0,0 +1 @@
legacy-peer-deps=true

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
16

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "pwa-chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}

32
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"editor.tabSize": 2,
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"workbench.settings.useSplitJSON": true,
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/*/**": true
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

42
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,42 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}

72
CREDITS Normal file
View File

@ -0,0 +1,72 @@
// -----------------------------------------------------------------------------------------------------
// @ 3rd party credits
// -----------------------------------------------------------------------------------------------------
// Flags
https://github.com/Yummygum/flagpack-core
// Icons
Material - https://material.io/tools/icons
Feather - https://feathericons.com/
Heroicons - https://github.com/refactoringui/heroicons
Iconsmind - https://iconsmind.com/
// Avatars
https://uifaces.co
// 404, 500 & Maintenance
https://undraw.co
// Mail app
Photo by Riccardo Chiarini on Unsplash - https://unsplash.com/photos/2VDa8bnLM8c
Photo by Johannes Plenio on Unsplash - https://unsplash.com/photos/RwHv7LgeC7s
Photo by Jamie Davies on Unsplash - https://unsplash.com/photos/Hao52Fu9-F8
Photo by Christian Joudrey on Unsplash - https://unsplash.com/photos/mWRR1xj95hg
// Profile page
Photo by Alex Knight on Unsplash - https://unsplash.com/photos/DpPutJwgyW8
// Cards
Photo by Kym Ellis on Unsplash - https://unsplash.com/photos/RPT3AjdXlZc
Photo by Patrick Hendry on Unsplash - https://unsplash.com/photos/Qgxk3PQsMiI
Photo by Hailey Kean on Unsplash - https://unsplash.com/photos/QxjsOlFNr_4
Photo by Nathan Anderson on Unsplash - https://unsplash.com/photos/mG8ShlWrMDI
Photo by Adrian Infernus on Unsplash - https://unsplash.com/photos/5apewqWk978
Photo by freestocks.org on Unsplash - https://unsplash.com/photos/c73TZ2sIU38
Photo by Tim Marshall on Unsplash - https://unsplash.com/photos/PKSCrmZdvwA
Photo by Daniel Koponyas on Unsplash - https://unsplash.com/photos/rbiLY6ZwvXQ
Photo by John Westrock on Unsplash - https://unsplash.com/photos/LCesauDseu8
Photo by Gabriel Sollmann on Unsplash - https://unsplash.com/photos/kFWj9y-tJB4
Photo by Kevin Wolf on Unsplash - https://unsplash.com/photos/BJyjgEdNTPs
Photo by Luca Bravo on Unsplash - https://unsplash.com/photos/hFzIoD0F_i8
Photo by Ian Baldwin on Unsplash - https://unsplash.com/photos/Dlj-SxxTlQ0
Photo by Ben Kolde on Unsplash - https://unsplash.com/photos/KRTFIBOfcFw
Photo by Chad Peltola on Unsplash - https://unsplash.com/photos/BTvQ2ET_iKc
Photo by rocknwool on Unsplash - https://unsplash.com/photos/r56oO1V5oms
Photo by Vita Vilcina on Unsplash - https://unsplash.com/photos/KtOid0FLjqU
Photo by Jia Ye on Unsplash - https://unsplash.com/photos/y8ZnQqgohLk
Photo by Parker Whitson on Unsplash - https://unsplash.com/photos/OlTYIqTjmVM
Photo by Dorian Hurst on Unsplash - https://unsplash.com/photos/a9uWPQlIbYc
Photo by Everaldo Coelho on Unsplash - https://unsplash.com/photos/KPaSCpklCZw
Photo by eberhard grossgasteiger on Unsplash - https://unsplash.com/photos/fh2JefbNlII
Photo by Orlova Maria on Unsplash - https://unsplash.com/photos/p8y4dWEMGMU
Photo by Jake Blucker on Unsplash - https://unsplash.com/photos/tMzCrBkM99Y
Photo by Jerry Zhang on Unsplash - https://unsplash.com/photos/oIBcow6n36s
Photo by John Cobb on Unsplash - https://unsplash.com/photos/IE_sifhay7o
Photo by Dan Gold on Unsplash - https://unsplash.com/photos/mDlhOIfGxNI
Photo by Ana Toma on Unsplash - https://unsplash.com/photos/XsGwe6gYg0c
Photo by Andrea on Unsplash - https://unsplash.com/photos/1AWY0N960Sk
Photo by Aswin on Unsplash - https://unsplash.com/photos/_roUcFWstas
Photo by Justin Kauffman on Unsplash - https://unsplash.com/photos/aWG_dqyhI0A
Photo by Barna Bartis on Unsplash - https://unsplash.com/photos/VVoBQqWrvkc
Photo by Kyle Hinkson on Unsplash - https://unsplash.com/photos/3439EnvnAGo
Photo by Spencer Watson on Unsplash - https://unsplash.com/photos/5TBf16GnHKg
Photo by adrian on Unsplash - https://unsplash.com/photos/1wrzvwoK8A4
Photo by Christopher Rusev on Unsplash - https://unsplash.com/photos/7gKWgCRixf0
Photo by Stephen Leonardi on Unsplash - https://unsplash.com/photos/MDmwQVgDHHM
Photo by Dwinanda Nurhanif Mujito on Unsplash - https://unsplash.com/photos/pKT5Mg16w_w
Photo by Humphrey Muleba on Unsplash - https://unsplash.com/photos/Zuvf5mxT5fs
Photo by adrian on Unsplash - https://unsplash.com/photos/PNRxLFPMyJY
Photo by Dahee Son on Unsplash - https://unsplash.com/photos/tV06QVJXVxU
Photo by Zachary Kyra-Derksen on Unsplash - https://unsplash.com/photos/vkqS7vLQUtg
Photo by Rodrigo Soares on Unsplash - https://unsplash.com/photos/8BFWBUkSqQo

6
LICENSE.md Normal file
View File

@ -0,0 +1,6 @@
Envato Standard License
Copyright (c) Sercan Yemen <sercanyemen@gmail.com>
This project is protected by Envato's Standard License. For more information,
check the official license page at [https://themeforest.net/licenses/standard](https://themeforest.net/licenses/standard)

View File

@ -1,92 +1,27 @@
# beteran-backend-app-browser # Fuse - Admin template and Starter project for Angular
This project was generated with [Angular CLI](https://github.com/angular/angular-cli)
## Development server
## Getting started Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
To make it easy for you to get started with GitLab, here's a list of recommended next steps. ## Code scaffolding
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Add your files ## Build
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
``` ## Running unit tests
cd existing_repo
git remote add origin https://gitlab.loafle.net/bet/beteran-backend-app-browser.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
- [ ] [Set up project integrations](https://gitlab.loafle.net/bet/beteran-backend-app-browser/-/settings/integrations) ## Running end-to-end tests
## Collaborate with your team Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) ## Further help
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

143
angular.json Normal file
View File

@ -0,0 +1,143 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"defaultCollection": "@angular-eslint/schematics"
},
"newProjectRoot": "projects",
"projects": {
"fuse": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/fuse",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"allowedCommonJsDependencies": [
"apexcharts",
"highlight.js",
"crypto-js"
],
"assets": [
"src/favicon-16x16.png",
"src/favicon-32x32.png",
"src/assets",
{
"glob": "_redirects",
"input": "src",
"output": "/"
},
{
"glob": "mdi.svg",
"input": "./node_modules/@mdi/angular-material",
"output": "./assets"
}
],
"stylePreprocessorOptions": {
"includePaths": ["src/@fuse/styles"]
},
"styles": [
"src/@fuse/styles/tailwind.scss",
"src/@fuse/styles/themes.scss",
"src/styles/vendors.scss",
"src/@fuse/styles/main.scss",
"src/styles/styles.scss",
"src/styles/tailwind.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "3mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "75kb",
"maximumError": "90kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"host": "0.0.0.0"
},
"configurations": {
"production": {
"browserTarget": "fuse:build:production"
},
"development": {
"browserTarget": "fuse:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "fuse:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon-16x16.png",
"src/favicon-32x32.png",
"src/assets"
],
"styles": ["src/styles/styles.scss"],
"scripts": []
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
}
}
}
},
"defaultProject": "fuse"
}

41
karma.conf.js Normal file
View File

@ -0,0 +1,41 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: "",
frameworks: ["jasmine", "@angular-devkit/build-angular"],
plugins: [
require("karma-jasmine"),
require("karma-chrome-launcher"),
require("karma-jasmine-html-reporter"),
require("karma-coverage"),
require("@angular-devkit/build-angular/plugins/karma"),
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require("path").join(__dirname, "./coverage/fuse"),
subdir: ".",
reporters: [{ type: "html" }, { type: "text-summary" }],
},
reporters: ["progress", "kjhtml"],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ["Chrome"],
singleRun: false,
restartOnFileChange: true,
});
};

25932
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

86
package.json Normal file
View File

@ -0,0 +1,86 @@
{
"name": "@fuse/starter",
"version": "14.2.0",
"description": "Fuse - Angular Admin Template and Starter Project",
"author": "https://themeforest.net/user/srcn",
"license": "https://themeforest.net/licenses/standard",
"private": true,
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "ng lint"
},
"dependencies": {
"@angular/animations": "13.2.3",
"@angular/cdk": "13.2.3",
"@angular/common": "13.2.3",
"@angular/compiler": "13.2.3",
"@angular/core": "13.2.3",
"@angular/forms": "13.2.3",
"@angular/material": "13.2.3",
"@angular/material-moment-adapter": "^13.2.3",
"@angular/platform-browser": "13.2.3",
"@angular/platform-browser-dynamic": "13.2.3",
"@angular/router": "13.2.3",
"@mdi/angular-material": "^7.0.96",
"@ngneat/transloco": "3.1.4",
"apexcharts": "3.33.1",
"crypto-js": "3.3.0",
"google-protobuf": "^3.20.1",
"highlight.js": "11.4.0",
"js-base64": "^3.7.2",
"lodash-es": "4.17.21",
"moment": "^2.29.4",
"nats.ws": "^1.8.1",
"ng-apexcharts": "1.7.0",
"ngx-markdown": "13.1.0",
"ngx-quill": "16.1.2",
"perfect-scrollbar": "1.5.3",
"quill": "1.3.7",
"rxjs": "7.5.4",
"tslib": "2.3.1",
"zone.js": "0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "13.2.4",
"@angular-eslint/builder": "13.1.0",
"@angular-eslint/eslint-plugin": "13.1.0",
"@angular-eslint/eslint-plugin-template": "13.1.0",
"@angular-eslint/schematics": "13.1.0",
"@angular-eslint/template-parser": "13.1.0",
"@angular/cli": "13.2.4",
"@angular/compiler-cli": "13.2.3",
"@tailwindcss/aspect-ratio": "0.4.0",
"@tailwindcss/line-clamp": "0.3.1",
"@tailwindcss/typography": "0.5.2",
"@types/chroma-js": "2.1.3",
"@types/crypto-js": "3.1.47",
"@types/google-protobuf": "^3.15.6",
"@types/highlight.js": "10.1.0",
"@types/jasmine": "3.10.3",
"@types/lodash": "4.14.178",
"@types/lodash-es": "4.17.6",
"@types/node": "12.20.46",
"@typescript-eslint/eslint-plugin": "5.12.0",
"@typescript-eslint/parser": "5.12.0",
"autoprefixer": "10.4.2",
"chroma-js": "2.4.2",
"eslint": "8.9.0",
"eslint-plugin-import": "2.25.4",
"eslint-plugin-jsdoc": "37.9.4",
"eslint-plugin-prefer-arrow": "1.2.3",
"jasmine-core": "4.0.0",
"karma": "6.3.16",
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "2.1.1",
"karma-jasmine": "4.0.1",
"karma-jasmine-html-reporter": "1.7.0",
"lodash": "4.17.21",
"postcss": "8.4.6",
"tailwindcss": "3.0.23",
"typescript": "4.5.5"
}
}

View File

@ -0,0 +1,12 @@
export class FuseAnimationCurves {
static standard = 'cubic-bezier(0.4, 0.0, 0.2, 1)';
static deceleration = 'cubic-bezier(0.0, 0.0, 0.2, 1)';
static acceleration = 'cubic-bezier(0.4, 0.0, 1, 1)';
static sharp = 'cubic-bezier(0.4, 0.0, 0.6, 1)';
}
export class FuseAnimationDurations {
static complex = '375ms';
static entering = '225ms';
static exiting = '195ms';
}

View File

@ -0,0 +1,34 @@
import { animate, state, style, transition, trigger } from '@angular/animations';
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
// -----------------------------------------------------------------------------------------------------
// @ Expand / collapse
// -----------------------------------------------------------------------------------------------------
const expandCollapse = trigger('expandCollapse',
[
state('void, collapsed',
style({
height: '0'
})
),
state('*, expanded',
style('*')
),
// Prevent the transition if the state is false
transition('void <=> false, collapsed <=> false, expanded <=> false', []),
// Transition
transition('void <=> *, collapsed <=> expanded',
animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
export { expandCollapse };

View File

@ -0,0 +1,330 @@
import { animate, state, style, transition, trigger } from '@angular/animations';
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
// -----------------------------------------------------------------------------------------------------
// @ Fade in
// -----------------------------------------------------------------------------------------------------
const fadeIn = trigger('fadeIn',
[
state('void',
style({
opacity: 0
})
),
state('*',
style({
opacity: 1
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade in top
// -----------------------------------------------------------------------------------------------------
const fadeInTop = trigger('fadeInTop',
[
state('void',
style({
opacity : 0,
transform: 'translate3d(0, -100%, 0)'
})
),
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade in bottom
// -----------------------------------------------------------------------------------------------------
const fadeInBottom = trigger('fadeInBottom',
[
state('void',
style({
opacity : 0,
transform: 'translate3d(0, 100%, 0)'
})
),
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade in left
// -----------------------------------------------------------------------------------------------------
const fadeInLeft = trigger('fadeInLeft',
[
state('void',
style({
opacity : 0,
transform: 'translate3d(-100%, 0, 0)'
})
),
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade in right
// -----------------------------------------------------------------------------------------------------
const fadeInRight = trigger('fadeInRight',
[
state('void',
style({
opacity : 0,
transform: 'translate3d(100%, 0, 0)'
})
),
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade out
// -----------------------------------------------------------------------------------------------------
const fadeOut = trigger('fadeOut',
[
state('*',
style({
opacity: 1
})
),
state('void',
style({
opacity: 0
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade out top
// -----------------------------------------------------------------------------------------------------
const fadeOutTop = trigger('fadeOutTop',
[
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
opacity : 0,
transform: 'translate3d(0, -100%, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade out bottom
// -----------------------------------------------------------------------------------------------------
const fadeOutBottom = trigger('fadeOutBottom',
[
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
opacity : 0,
transform: 'translate3d(0, 100%, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade out left
// -----------------------------------------------------------------------------------------------------
const fadeOutLeft = trigger('fadeOutLeft',
[
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
opacity : 0,
transform: 'translate3d(-100%, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Fade out right
// -----------------------------------------------------------------------------------------------------
const fadeOutRight = trigger('fadeOutRight',
[
state('*',
style({
opacity : 1,
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
opacity : 0,
transform: 'translate3d(100%, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
export { fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight, fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight };

View File

@ -0,0 +1 @@
export * from '@fuse/animations/public-api';

View File

@ -0,0 +1,15 @@
import { expandCollapse } from '@fuse/animations/expand-collapse';
import { fadeIn, fadeInBottom, fadeInLeft, fadeInRight, fadeInTop, fadeOut, fadeOutBottom, fadeOutLeft, fadeOutRight, fadeOutTop } from '@fuse/animations/fade';
import { shake } from '@fuse/animations/shake';
import { slideInBottom, slideInLeft, slideInRight, slideInTop, slideOutBottom, slideOutLeft, slideOutRight, slideOutTop } from '@fuse/animations/slide';
import { zoomIn, zoomOut } from '@fuse/animations/zoom';
export const fuseAnimations = [
expandCollapse,
fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight,
fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight,
shake,
slideInTop, slideInBottom, slideInLeft, slideInRight,
slideOutTop, slideOutBottom, slideOutLeft, slideOutRight,
zoomIn, zoomOut
];

View File

@ -0,0 +1,73 @@
import { animate, keyframes, style, transition, trigger } from '@angular/animations';
// -----------------------------------------------------------------------------------------------------
// @ Shake
// -----------------------------------------------------------------------------------------------------
const shake = trigger('shake',
[
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *, * => true',
[
animate('{{timings}}',
keyframes([
style({
transform: 'translate3d(0, 0, 0)',
offset : 0
}),
style({
transform: 'translate3d(-10px, 0, 0)',
offset : 0.1
}),
style({
transform: 'translate3d(10px, 0, 0)',
offset : 0.2
}),
style({
transform: 'translate3d(-10px, 0, 0)',
offset : 0.3
}),
style({
transform: 'translate3d(10px, 0, 0)',
offset : 0.4
}),
style({
transform: 'translate3d(-10px, 0, 0)',
offset : 0.5
}),
style({
transform: 'translate3d(10px, 0, 0)',
offset : 0.6
}),
style({
transform: 'translate3d(-10px, 0, 0)',
offset : 0.7
}),
style({
transform: 'translate3d(10px, 0, 0)',
offset : 0.8
}),
style({
transform: 'translate3d(-10px, 0, 0)',
offset : 0.9
}),
style({
transform: 'translate3d(0, 0, 0)',
offset : 1
})
])
)
],
{
params: {
timings: '0.8s cubic-bezier(0.455, 0.03, 0.515, 0.955)'
}
}
)
]
);
export { shake };

View File

@ -0,0 +1,252 @@
import { animate, state, style, transition, trigger } from '@angular/animations';
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
// -----------------------------------------------------------------------------------------------------
// @ Slide in top
// -----------------------------------------------------------------------------------------------------
const slideInTop = trigger('slideInTop',
[
state('void',
style({
transform: 'translate3d(0, -100%, 0)'
})
),
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide in bottom
// -----------------------------------------------------------------------------------------------------
const slideInBottom = trigger('slideInBottom',
[
state('void',
style({
transform: 'translate3d(0, 100%, 0)'
})
),
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide in left
// -----------------------------------------------------------------------------------------------------
const slideInLeft = trigger('slideInLeft',
[
state('void',
style({
transform: 'translate3d(-100%, 0, 0)'
})
),
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide in right
// -----------------------------------------------------------------------------------------------------
const slideInRight = trigger('slideInRight',
[
state('void',
style({
transform: 'translate3d(100%, 0, 0)'
})
),
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide out top
// -----------------------------------------------------------------------------------------------------
const slideOutTop = trigger('slideOutTop',
[
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
transform: 'translate3d(0, -100%, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide out bottom
// -----------------------------------------------------------------------------------------------------
const slideOutBottom = trigger('slideOutBottom',
[
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
transform: 'translate3d(0, 100%, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide out left
// -----------------------------------------------------------------------------------------------------
const slideOutLeft = trigger('slideOutLeft',
[
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
transform: 'translate3d(-100%, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Slide out right
// -----------------------------------------------------------------------------------------------------
const slideOutRight = trigger('slideOutRight',
[
state('*',
style({
transform: 'translate3d(0, 0, 0)'
})
),
state('void',
style({
transform: 'translate3d(100%, 0, 0)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
export { slideInTop, slideInBottom, slideInLeft, slideInRight, slideOutTop, slideOutBottom, slideOutLeft, slideOutRight };

View File

@ -0,0 +1,73 @@
import { animate, state, style, transition, trigger } from '@angular/animations';
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
// -----------------------------------------------------------------------------------------------------
// @ Zoom in
// -----------------------------------------------------------------------------------------------------
const zoomIn = trigger('zoomIn',
[
state('void',
style({
opacity : 0,
transform: 'scale(0.5)'
})
),
state('*',
style({
opacity : 1,
transform: 'scale(1)'
})
),
// Prevent the transition if the state is false
transition('void => false', []),
// Transition
transition('void => *', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`
}
}
)
]
);
// -----------------------------------------------------------------------------------------------------
// @ Zoom out
// -----------------------------------------------------------------------------------------------------
const zoomOut = trigger('zoomOut',
[
state('*',
style({
opacity : 1,
transform: 'scale(1)'
})
),
state('void',
style({
opacity : 0,
transform: 'scale(0.5)'
})
),
// Prevent the transition if the state is false
transition('false => void', []),
// Transition
transition('* => void', animate('{{timings}}'),
{
params: {
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`
}
}
)
]
);
export { zoomIn, zoomOut };

View File

@ -0,0 +1,76 @@
<div
class="fuse-alert-container"
*ngIf="!dismissible || (dismissible && !dismissed)"
[@fadeIn]="!dismissed"
[@fadeOut]="!dismissed"
>
<!-- Border -->
<div class="fuse-alert-border" *ngIf="appearance === 'border'"></div>
<!-- Icon -->
<div class="fuse-alert-icon" *ngIf="showIcon">
<!-- Custom icon -->
<div class="fuse-alert-custom-icon">
<ng-content select="[fuseAlertIcon]"></ng-content>
</div>
<!-- Default icons -->
<div class="fuse-alert-default-icon">
<mat-icon
*ngIf="type === 'primary'"
[svgIcon]="'heroicons_solid:check-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'accent'"
[svgIcon]="'heroicons_solid:check-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'warn'"
[svgIcon]="'heroicons_solid:x-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'basic'"
[svgIcon]="'heroicons_solid:check-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'info'"
[svgIcon]="'heroicons_solid:information-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'success'"
[svgIcon]="'heroicons_solid:check-circle'"
></mat-icon>
<mat-icon
*ngIf="type === 'warning'"
[svgIcon]="'heroicons_solid:exclamation'"
></mat-icon>
<mat-icon
*ngIf="type === 'error'"
[svgIcon]="'heroicons_solid:x-circle'"
></mat-icon>
</div>
</div>
<!-- Content -->
<div class="fuse-alert-content">
<div class="fuse-alert-title">
<ng-content select="[fuseAlertTitle]"></ng-content>
</div>
<div class="fuse-alert-message">
<ng-content></ng-content>
</div>
</div>
<!-- Dismiss button -->
<button class="fuse-alert-dismiss-button" mat-icon-button (click)="dismiss()">
<mat-icon [svgIcon]="'heroicons_solid:x'"></mat-icon>
</button>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
HostBinding,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import { filter, Subject, takeUntil } from 'rxjs';
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
import { fuseAnimations } from '@fuse/animations';
import {
FuseAlertAppearance,
FuseAlertType,
} from '@fuse/components/alert/alert.types';
import { FuseAlertService } from '@fuse/components/alert/alert.service';
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
@Component({
selector: 'fuse-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.scss'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
animations: fuseAnimations,
exportAs: 'fuseAlert',
})
export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy {
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_dismissible: BooleanInput;
static ngAcceptInputType_dismissed: BooleanInput;
static ngAcceptInputType_showIcon: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() appearance: FuseAlertAppearance = 'soft';
@Input() dismissed: boolean = false;
@Input() dismissible: boolean = false;
@Input() name: string = this._fuseUtilsService.randomId();
@Input() showIcon: boolean = true;
@Input() type: FuseAlertType = 'primary';
@Output() readonly dismissedChanged: EventEmitter<boolean> =
new EventEmitter<boolean>();
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseAlertService: FuseAlertService,
private _fuseUtilsService: FuseUtilsService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Host binding for component classes
*/
@HostBinding('class') get classList(): any {
return {
'fuse-alert-appearance-border': this.appearance === 'border',
'fuse-alert-appearance-fill': this.appearance === 'fill',
'fuse-alert-appearance-outline': this.appearance === 'outline',
'fuse-alert-appearance-soft': this.appearance === 'soft',
'fuse-alert-dismissed': this.dismissed,
'fuse-alert-dismissible': this.dismissible,
'fuse-alert-show-icon': this.showIcon,
'fuse-alert-type-primary': this.type === 'primary',
'fuse-alert-type-accent': this.type === 'accent',
'fuse-alert-type-warn': this.type === 'warn',
'fuse-alert-type-basic': this.type === 'basic',
'fuse-alert-type-info': this.type === 'info',
'fuse-alert-type-success': this.type === 'success',
'fuse-alert-type-warning': this.type === 'warning',
'fuse-alert-type-error': this.type === 'error',
};
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Dismissed
if ('dismissed' in changes) {
// Coerce the value to a boolean
this.dismissed = coerceBooleanProperty(changes['dismissed'].currentValue);
// Dismiss/show the alert
this._toggleDismiss(this.dismissed);
}
// Dismissible
if ('dismissible' in changes) {
// Coerce the value to a boolean
this.dismissible = coerceBooleanProperty(
changes['dismissed'].currentValue
);
}
// Show icon
if ('showIcon' in changes) {
// Coerce the value to a boolean
this.showIcon = coerceBooleanProperty(changes['showIcon'].currentValue);
}
}
/**
* On init
*/
ngOnInit(): void {
// Subscribe to the dismiss calls
this._fuseAlertService.onDismiss
.pipe(
filter((name: any) => this.name === name),
takeUntil(this._unsubscribeAll)
)
.subscribe(() => {
// Dismiss the alert
this.dismiss();
});
// Subscribe to the show calls
this._fuseAlertService.onShow
.pipe(
filter((name: any) => this.name === name),
takeUntil(this._unsubscribeAll)
)
.subscribe(() => {
// Show the alert
this.show();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Dismiss the alert
*/
dismiss(): void {
// Return if the alert is already dismissed
if (this.dismissed) {
return;
}
// Dismiss the alert
this._toggleDismiss(true);
}
/**
* Show the dismissed alert
*/
show(): void {
// Return if the alert is already showing
if (!this.dismissed) {
return;
}
// Show the alert
this._toggleDismiss(false);
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Dismiss/show the alert
*
* @param dismissed
* @private
*/
private _toggleDismiss(dismissed: boolean): void {
// Return if the alert is not dismissible
if (!this.dismissible) {
return;
}
// Set the dismissed
this.dismissed = dismissed;
// Execute the observable
this.dismissedChanged.next(this.dismissed);
// Notify the change detector
this._changeDetectorRef.markForCheck();
}
}

View File

@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { FuseAlertComponent } from '@fuse/components/alert/alert.component';
@NgModule({
declarations: [
FuseAlertComponent
],
imports : [
CommonModule,
MatButtonModule,
MatIconModule
],
exports : [
FuseAlertComponent
]
})
export class FuseAlertModule
{
}

View File

@ -0,0 +1,77 @@
import { Injectable } from '@angular/core';
import { Observable, ReplaySubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class FuseAlertService
{
private readonly _onDismiss: ReplaySubject<string> = new ReplaySubject<string>(1);
private readonly _onShow: ReplaySubject<string> = new ReplaySubject<string>(1);
/**
* Constructor
*/
constructor()
{
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Getter for onDismiss
*/
get onDismiss(): Observable<any>
{
return this._onDismiss.asObservable();
}
/**
* Getter for onShow
*/
get onShow(): Observable<any>
{
return this._onShow.asObservable();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Dismiss the alert
*
* @param name
*/
dismiss(name: string): void
{
// Return if the name is not provided
if ( !name )
{
return;
}
// Execute the observable
this._onDismiss.next(name);
}
/**
* Show the dismissed alert
*
* @param name
*/
show(name: string): void
{
// Return if the name is not provided
if ( !name )
{
return;
}
// Execute the observable
this._onShow.next(name);
}
}

View File

@ -0,0 +1,15 @@
export type FuseAlertAppearance =
| 'border'
| 'fill'
| 'outline'
| 'soft';
export type FuseAlertType =
| 'primary'
| 'accent'
| 'warn'
| 'basic'
| 'info'
| 'success'
| 'warning'
| 'error';

View File

@ -0,0 +1 @@
export * from '@fuse/components/alert/public-api';

View File

@ -0,0 +1,4 @@
export * from '@fuse/components/alert/alert.component';
export * from '@fuse/components/alert/alert.module';
export * from '@fuse/components/alert/alert.service';
export * from '@fuse/components/alert/alert.types';

View File

@ -0,0 +1,23 @@
<!-- Flippable card -->
<ng-container *ngIf="flippable">
<!-- Front -->
<div class="fuse-card-front">
<ng-content select="[fuseCardFront]"></ng-content>
</div>
<!-- Back -->
<div class="fuse-card-back">
<ng-content select="[fuseCardBack]"></ng-content>
</div>
</ng-container>
<!-- Normal card -->
<ng-container *ngIf="!flippable">
<!-- Content -->
<ng-content></ng-content>
<!-- Expansion -->
<div class="fuse-card-expansion" *ngIf="expanded" [@expandCollapse]>
<ng-content select="[fuseCardExpansion]"></ng-content>
</div>
</ng-container>

View File

@ -0,0 +1,63 @@
fuse-card {
position: relative;
display: flex;
overflow: hidden;
@apply rounded-2xl shadow bg-card;
/* Flippable */
&.fuse-card-flippable {
border-radius: 0;
overflow: visible;
transform-style: preserve-3d;
transition: transform 1s;
perspective: 600px;
background: transparent;
@apply shadow-none;
&.fuse-card-face-back {
.fuse-card-front {
visibility: hidden;
opacity: 0;
transform: rotateY(180deg);
}
.fuse-card-back {
visibility: visible;
opacity: 1;
transform: rotateY(360deg);
}
}
.fuse-card-front,
.fuse-card-back {
display: flex;
flex-direction: column;
flex: 1 1 auto;
z-index: 10;
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
backface-visibility: hidden;
@apply rounded-2xl shadow bg-card;
}
.fuse-card-front {
position: relative;
opacity: 1;
visibility: visible;
transform: rotateY(0deg);
overflow: hidden;
}
.fuse-card-back {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0;
visibility: hidden;
transform: rotateY(180deg);
overflow: hidden auto;
}
}
}

View File

@ -0,0 +1,74 @@
import {
Component,
HostBinding,
Input,
OnChanges,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
import { fuseAnimations } from '@fuse/animations';
import { FuseCardFace } from '@fuse/components/card/card.types';
@Component({
selector: 'fuse-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
encapsulation: ViewEncapsulation.None,
animations: fuseAnimations,
exportAs: 'fuseCard',
})
export class FuseCardComponent implements OnChanges {
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_expanded: BooleanInput;
static ngAcceptInputType_flippable: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() expanded: boolean = false;
@Input() face: FuseCardFace = 'front';
@Input() flippable: boolean = false;
/**
* Constructor
*/
constructor() {}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Host binding for component classes
*/
@HostBinding('class') get classList(): any {
return {
'fuse-card-expanded': this.expanded,
'fuse-card-face-back': this.flippable && this.face === 'back',
'fuse-card-face-front': this.flippable && this.face === 'front',
'fuse-card-flippable': this.flippable,
};
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Expanded
if ('expanded' in changes) {
// Coerce the value to a boolean
this.expanded = coerceBooleanProperty(changes['expanded'].currentValue);
}
// Flippable
if ('flippable' in changes) {
// Coerce the value to a boolean
this.flippable = coerceBooleanProperty(changes['flippable'].currentValue);
}
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FuseCardComponent } from '@fuse/components/card/card.component';
@NgModule({
declarations: [
FuseCardComponent
],
imports : [
CommonModule
],
exports : [
FuseCardComponent
]
})
export class FuseCardModule
{
}

View File

@ -0,0 +1,3 @@
export type FuseCardFace =
| 'front'
| 'back';

View File

@ -0,0 +1 @@
export * from '@fuse/components/card/public-api';

View File

@ -0,0 +1,2 @@
export * from '@fuse/components/card/card.component';
export * from '@fuse/components/card/card.module';

View File

@ -0,0 +1,3 @@
<div class="fuse-drawer-content">
<ng-content></ng-content>
</div>

View File

@ -0,0 +1,133 @@
/* Variables */
:root {
--fuse-drawer-width: 320px;
}
fuse-drawer {
position: relative;
display: flex;
flex-direction: column;
flex: 1 1 auto;
width: var(--fuse-drawer-width);
min-width: var(--fuse-drawer-width);
max-width: var(--fuse-drawer-width);
z-index: 300;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .35);
@apply bg-card;
/* Animations */
&.fuse-drawer-animations-enabled {
transition-duration: 400ms;
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1);
transition-property: visibility, margin-left, margin-right, transform, width, max-width, min-width;
.fuse-drawer-content {
transition-duration: 400ms;
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1);
transition-property: width, max-width, min-width;
}
}
/* Over mode */
&.fuse-drawer-mode-over {
position: absolute;
top: 0;
bottom: 0;
/* Fixed mode */
&.fuse-drawer-fixed {
position: fixed;
}
}
/* Left position */
&.fuse-drawer-position-left {
/* Side mode */
&.fuse-drawer-mode-side {
margin-left: calc(var(--fuse-drawer-width) * -1);
&.fuse-drawer-opened {
margin-left: 0;
}
}
/* Over mode */
&.fuse-drawer-mode-over {
left: 0;
transform: translate3d(-100%, 0, 0);
&.fuse-drawer-opened {
transform: translate3d(0, 0, 0);
}
}
/* Content */
.fuse-drawer-content {
left: 0;
}
}
/* Right position */
&.fuse-drawer-position-right {
/* Side mode */
&.fuse-drawer-mode-side {
margin-right: calc(var(--fuse-drawer-width) * -1);
&.fuse-drawer-opened {
margin-right: 0;
}
}
/* Over mode */
&.fuse-drawer-mode-over {
right: 0;
transform: translate3d(100%, 0, 0);
&.fuse-drawer-opened {
transform: translate3d(0, 0, 0);
}
}
/* Content */
.fuse-drawer-content {
right: 0;
}
}
/* Content */
.fuse-drawer-content {
position: absolute;
display: flex;
flex: 1 1 auto;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
overflow: hidden;
@apply bg-card;
}
}
/* Overlay */
.fuse-drawer-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 299;
opacity: 1;
background-color: rgba(0, 0, 0, 0.6);
/* Fixed mode */
&.fuse-drawer-overlay-fixed {
position: fixed;
}
/* Transparent overlay */
&.fuse-drawer-overlay-transparent {
background-color: transparent;
}
}

View File

@ -0,0 +1,434 @@
import {
Component,
ElementRef,
EventEmitter,
HostBinding,
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
Renderer2,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import {
animate,
AnimationBuilder,
AnimationPlayer,
style,
} from '@angular/animations';
import {
FuseDrawerMode,
FuseDrawerPosition,
} from '@fuse/components/drawer/drawer.types';
import { FuseDrawerService } from '@fuse/components/drawer/drawer.service';
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
@Component({
selector: 'fuse-drawer',
templateUrl: './drawer.component.html',
styleUrls: ['./drawer.component.scss'],
encapsulation: ViewEncapsulation.None,
exportAs: 'fuseDrawer',
})
export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy {
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_fixed: BooleanInput;
static ngAcceptInputType_opened: BooleanInput;
static ngAcceptInputType_transparentOverlay: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() fixed: boolean = false;
@Input() mode: FuseDrawerMode = 'side';
@Input() name: string = this._fuseUtilsService.randomId();
@Input() opened: boolean = false;
@Input() position: FuseDrawerPosition = 'left';
@Input() transparentOverlay: boolean = false;
@Output() readonly fixedChanged: EventEmitter<boolean> =
new EventEmitter<boolean>();
@Output() readonly modeChanged: EventEmitter<FuseDrawerMode> =
new EventEmitter<FuseDrawerMode>();
@Output() readonly openedChanged: EventEmitter<boolean> =
new EventEmitter<boolean>();
@Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> =
new EventEmitter<FuseDrawerPosition>();
private _animationsEnabled: boolean = false;
private _hovered: boolean = false;
private _overlay?: HTMLElement;
private _player?: AnimationPlayer;
/**
* Constructor
*/
constructor(
private _animationBuilder: AnimationBuilder,
private _elementRef: ElementRef,
private _renderer2: Renderer2,
private _fuseDrawerService: FuseDrawerService,
private _fuseUtilsService: FuseUtilsService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Host binding for component classes
*/
@HostBinding('class') get classList(): any {
return {
'fuse-drawer-animations-enabled': this._animationsEnabled,
'fuse-drawer-fixed': this.fixed,
'fuse-drawer-hover': this._hovered,
[`fuse-drawer-mode-${this.mode}`]: true,
'fuse-drawer-opened': this.opened,
[`fuse-drawer-position-${this.position}`]: true,
};
}
/**
* Host binding for component inline styles
*/
@HostBinding('style') get styleList(): any {
return {
visibility: this.opened ? 'visible' : 'hidden',
};
}
// -----------------------------------------------------------------------------------------------------
// @ Decorated methods
// -----------------------------------------------------------------------------------------------------
/**
* On mouseenter
*
* @private
*/
@HostListener('mouseenter')
private _onMouseenter(): void {
// Enable the animations
this._enableAnimations();
// Set the hovered
this._hovered = true;
}
/**
* On mouseleave
*
* @private
*/
@HostListener('mouseleave')
private _onMouseleave(): void {
// Enable the animations
this._enableAnimations();
// Set the hovered
this._hovered = false;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Fixed
if ('fixed' in changes) {
// Coerce the value to a boolean
this.fixed = coerceBooleanProperty(changes['fixed'].currentValue);
// Execute the observable
this.fixedChanged.next(this.fixed);
}
// Mode
if ('mode' in changes) {
// Get the previous and current values
const previousMode = changes['mode'].previousValue;
const currentMode = changes['mode'].currentValue;
// Disable the animations
this._disableAnimations();
// If the mode changes: 'over -> side'
if (previousMode === 'over' && currentMode === 'side') {
// Hide the overlay
this._hideOverlay();
}
// If the mode changes: 'side -> over'
if (previousMode === 'side' && currentMode === 'over') {
// If the drawer is opened
if (this.opened) {
// Show the overlay
this._showOverlay();
}
}
// Execute the observable
this.modeChanged.next(currentMode);
// Enable the animations after a delay
// The delay must be bigger than the current transition-duration
// to make sure nothing will be animated while the mode is changing
setTimeout(() => {
this._enableAnimations();
}, 500);
}
// Opened
if ('opened' in changes) {
// Coerce the value to a boolean
const open = coerceBooleanProperty(changes['opened'].currentValue);
// Open/close the drawer
this._toggleOpened(open);
}
// Position
if ('position' in changes) {
// Execute the observable
this.positionChanged.next(this.position);
}
// Transparent overlay
if ('transparentOverlay' in changes) {
// Coerce the value to a boolean
this.transparentOverlay = coerceBooleanProperty(
changes['transparentOverlay'].currentValue
);
}
}
/**
* On init
*/
ngOnInit(): void {
// Register the drawer
this._fuseDrawerService.registerComponent(this.name, this);
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Finish the animation
if (this._player) {
this._player.finish();
}
// Deregister the drawer from the registry
this._fuseDrawerService.deregisterComponent(this.name);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open the drawer
*/
open(): void {
// Return if the drawer has already opened
if (this.opened) {
return;
}
// Open the drawer
this._toggleOpened(true);
}
/**
* Close the drawer
*/
close(): void {
// Return if the drawer has already closed
if (!this.opened) {
return;
}
// Close the drawer
this._toggleOpened(false);
}
/**
* Toggle the drawer
*/
toggle(): void {
if (this.opened) {
this.close();
} else {
this.open();
}
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Enable the animations
*
* @private
*/
private _enableAnimations(): void {
// Return if the animations are already enabled
if (this._animationsEnabled) {
return;
}
// Enable the animations
this._animationsEnabled = true;
}
/**
* Disable the animations
*
* @private
*/
private _disableAnimations(): void {
// Return if the animations are already disabled
if (!this._animationsEnabled) {
return;
}
// Disable the animations
this._animationsEnabled = false;
}
/**
* Show the backdrop
*
* @private
*/
private _showOverlay(): void {
// Create the backdrop element
this._overlay = this._renderer2.createElement('div');
// Return if overlay couldn't be create for some reason
if (!this._overlay) {
return;
}
// Add a class to the backdrop element
this._overlay.classList.add('fuse-drawer-overlay');
// Add a class depending on the fixed option
if (this.fixed) {
this._overlay.classList.add('fuse-drawer-overlay-fixed');
}
// Add a class depending on the transparentOverlay option
if (this.transparentOverlay) {
this._overlay.classList.add('fuse-drawer-overlay-transparent');
}
// Append the backdrop to the parent of the drawer
this._renderer2.appendChild(
this._elementRef.nativeElement.parentElement,
this._overlay
);
// Create the enter animation and attach it to the player
this._player = this._animationBuilder
.build([
style({ opacity: 0 }),
animate(
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
style({ opacity: 1 })
),
])
.create(this._overlay);
// Once the animation is done...
this._player.onDone(() => {
// Destroy the player
this._player?.destroy();
this._player = undefined;
});
// Play the animation
this._player.play();
// Add an event listener to the overlay
this._overlay.addEventListener('click', () => {
this.close();
});
}
/**
* Hide the backdrop
*
* @private
*/
private _hideOverlay(): void {
if (!this._overlay) {
return;
}
// Create the leave animation and attach it to the player
this._player = this._animationBuilder
.build([
animate(
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
style({ opacity: 0 })
),
])
.create(this._overlay);
// Play the animation
this._player.play();
// Once the animation is done...
this._player.onDone(() => {
// Destroy the player
this._player?.destroy();
this._player = undefined;
// If the backdrop still exists...
if (this._overlay) {
// Remove the backdrop
this._overlay.parentNode?.removeChild(this._overlay);
this._overlay = undefined;
}
});
}
/**
* Open/close the drawer
*
* @param open
* @private
*/
private _toggleOpened(open: boolean): void {
// Set the opened
this.opened = open;
// Enable the animations
this._enableAnimations();
// If the mode is 'over'
if (this.mode === 'over') {
// If the drawer opens, show the overlay
if (open) {
this._showOverlay();
}
// Otherwise, close the overlay
else {
this._hideOverlay();
}
}
// Execute the observable
this.openedChanged.next(open);
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FuseDrawerComponent } from '@fuse/components/drawer/drawer.component';
@NgModule({
declarations: [
FuseDrawerComponent
],
imports : [
CommonModule
],
exports : [
FuseDrawerComponent
]
})
export class FuseDrawerModule
{
}

View File

@ -0,0 +1,52 @@
import { Injectable } from '@angular/core';
import { FuseDrawerComponent } from '@fuse/components/drawer/drawer.component';
@Injectable({
providedIn: 'root'
})
export class FuseDrawerService
{
private _componentRegistry: Map<string, FuseDrawerComponent> = new Map<string, FuseDrawerComponent>();
/**
* Constructor
*/
constructor()
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Register drawer component
*
* @param name
* @param component
*/
registerComponent(name: string, component: FuseDrawerComponent): void
{
this._componentRegistry.set(name, component);
}
/**
* Deregister drawer component
*
* @param name
*/
deregisterComponent(name: string): void
{
this._componentRegistry.delete(name);
}
/**
* Get drawer component from the registry
*
* @param name
*/
getComponent(name: string): FuseDrawerComponent | undefined
{
return this._componentRegistry.get(name);
}
}

View File

@ -0,0 +1,7 @@
export type FuseDrawerMode =
| 'over'
| 'side';
export type FuseDrawerPosition =
| 'left'
| 'right';

View File

@ -0,0 +1 @@
export * from '@fuse/components/drawer/public-api';

View File

@ -0,0 +1,4 @@
export * from '@fuse/components/drawer/drawer.component';
export * from '@fuse/components/drawer/drawer.module';
export * from '@fuse/components/drawer/drawer.service';
export * from '@fuse/components/drawer/drawer.types';

View File

@ -0,0 +1,13 @@
<!-- Button -->
<button
mat-icon-button
[matTooltip]="tooltip || 'Toggle Fullscreen'"
(click)="toggleFullscreen()"
>
<ng-container [ngTemplateOutlet]="iconTpl || defaultIconTpl"></ng-container>
</button>
<!-- Default icon -->
<ng-template #defaultIconTpl>
<mat-icon [svgIcon]="'heroicons_outline:arrows-expand'"></mat-icon>
</ng-template>

View File

@ -0,0 +1,155 @@
import {
ChangeDetectionStrategy,
Component,
Inject,
Input,
OnInit,
TemplateRef,
ViewEncapsulation,
} from '@angular/core';
import { DOCUMENT } from '@angular/common';
import {
FSDocument,
FSDocumentElement,
} from '@fuse/components/fullscreen/fullscreen.types';
@Component({
selector: 'fuse-fullscreen',
templateUrl: './fullscreen.component.html',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
exportAs: 'fuseFullscreen',
})
export class FuseFullscreenComponent implements OnInit {
@Input() iconTpl?: TemplateRef<any>;
@Input() tooltip?: string;
private _fsDoc: FSDocument;
private _fsDocEl?: FSDocumentElement;
private _isFullscreen: boolean = false;
/**
* Constructor
*/
constructor(@Inject(DOCUMENT) private _document: Document) {
this._fsDoc = _document as FSDocument;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
this._fsDocEl = document.documentElement as FSDocumentElement;
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Toggle the fullscreen mode
*/
toggleFullscreen(): void {
// Check if the fullscreen is open
this._isFullscreen = this._getBrowserFullscreenElement() !== null;
// Toggle the fullscreen
if (this._isFullscreen) {
this._closeFullscreen();
} else {
this._openFullscreen();
}
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Get browser's fullscreen element
*
* @private
*/
private _getBrowserFullscreenElement(): Element | null {
if (typeof this._fsDoc.fullscreenElement !== 'undefined') {
return this._fsDoc.fullscreenElement;
}
if (typeof this._fsDoc.mozFullScreenElement !== 'undefined') {
return this._fsDoc.mozFullScreenElement;
}
if (typeof this._fsDoc.msFullscreenElement !== 'undefined') {
return this._fsDoc.msFullscreenElement;
}
if (typeof this._fsDoc.webkitFullscreenElement !== 'undefined') {
return this._fsDoc.webkitFullscreenElement;
}
throw new Error('Fullscreen mode is not supported by this browser');
}
/**
* Open the fullscreen
*
* @private
*/
private _openFullscreen(): void {
if (this._fsDocEl?.requestFullscreen) {
this._fsDocEl.requestFullscreen();
return;
}
// Firefox
if (this._fsDocEl?.mozRequestFullScreen) {
this._fsDocEl.mozRequestFullScreen();
return;
}
// Chrome, Safari and Opera
if (this._fsDocEl?.webkitRequestFullscreen) {
this._fsDocEl.webkitRequestFullscreen();
return;
}
// IE/Edge
if (this._fsDocEl?.msRequestFullscreen) {
this._fsDocEl.msRequestFullscreen();
return;
}
}
/**
* Close the fullscreen
*
* @private
*/
private _closeFullscreen(): void {
if (this._fsDoc.exitFullscreen) {
this._fsDoc.exitFullscreen();
return;
}
// Firefox
if (this._fsDoc.mozCancelFullScreen) {
this._fsDoc.mozCancelFullScreen();
return;
}
// Chrome, Safari and Opera
if (this._fsDoc.webkitExitFullscreen) {
this._fsDoc.webkitExitFullscreen();
return;
}
// IE/Edge
else if (this._fsDoc.msExitFullscreen) {
this._fsDoc.msExitFullscreen();
return;
}
}
}

View File

@ -0,0 +1,24 @@
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { FuseFullscreenComponent } from '@fuse/components/fullscreen/fullscreen.component';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [
FuseFullscreenComponent
],
imports : [
MatButtonModule,
MatIconModule,
MatTooltipModule,
CommonModule
],
exports : [
FuseFullscreenComponent
]
})
export class FuseFullscreenModule
{
}

View File

@ -0,0 +1,16 @@
export interface FSDocument extends HTMLDocument
{
mozFullScreenElement?: Element;
mozCancelFullScreen?: () => void;
msFullscreenElement?: Element;
msExitFullscreen?: () => void;
webkitFullscreenElement?: Element;
webkitExitFullscreen?: () => void;
}
export interface FSDocumentElement extends HTMLElement
{
mozRequestFullScreen?: () => void;
msRequestFullscreen?: () => void;
webkitRequestFullscreen?: () => void;
}

View File

@ -0,0 +1 @@
export * from '@fuse/components/fullscreen/public-api';

View File

@ -0,0 +1,3 @@
export * from '@fuse/components/fullscreen/fullscreen.component';
export * from '@fuse/components/fullscreen/fullscreen.module';
export * from '@fuse/components/fullscreen/fullscreen.types';

View File

@ -0,0 +1,11 @@
<ng-content></ng-content>
<!-- @formatter:off -->
<ng-template let-highlightedCode="highlightedCode" let-lang="lang">
<div class="fuse-highlight fuse-highlight-code-container">
<pre
[ngClass]="'language-' + lang"
><code [ngClass]="'language-' + lang" [innerHTML]="highlightedCode"></code></pre>
</div>
</ng-template>
<!-- @formatter:on -->

View File

@ -0,0 +1,3 @@
textarea[fuse-highlight] {
display: none;
}

View File

@ -0,0 +1,140 @@
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EmbeddedViewRef,
Input,
OnChanges,
Renderer2,
SecurityContext,
SimpleChanges,
TemplateRef,
ViewChild,
ViewContainerRef,
ViewEncapsulation,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { FuseHighlightService } from '@fuse/components/highlight/highlight.service';
@Component({
selector: 'textarea[fuse-highlight]',
templateUrl: './highlight.component.html',
styleUrls: ['./highlight.component.scss'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
exportAs: 'fuseHighlight',
})
export class FuseHighlightComponent implements OnChanges, AfterViewInit {
@Input() code?: string;
@Input() lang?: string;
@ViewChild(TemplateRef) templateRef!: TemplateRef<any>;
highlightedCode: string | null = null;
private _viewRef?: EmbeddedViewRef<any>;
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _domSanitizer: DomSanitizer,
private _elementRef: ElementRef,
private _renderer2: Renderer2,
private _fuseHighlightService: FuseHighlightService,
private _viewContainerRef: ViewContainerRef
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Code & Lang
if ('code' in changes || 'lang' in changes) {
// Return if the viewContainerRef is not available
if (!this._viewContainerRef.length) {
return;
}
// Highlight and insert the code
this._highlightAndInsert();
}
}
/**
* After view init
*/
ngAfterViewInit(): void {
// Return if there is no language set
if (!this.lang) {
return;
}
// If there is no code input, get the code from
// the textarea
if (!this.code) {
// Get the code
this.code = this._elementRef.nativeElement.value;
}
// Highlight and insert
this._highlightAndInsert();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Highlight and insert the highlighted code
*
* @private
*/
private _highlightAndInsert(): void {
// Return if the template reference is not available
if (!this.templateRef) {
return;
}
// Return if the code or language is not defined
if (!this.code || !this.lang) {
return;
}
// Destroy the component if there is already one
if (this._viewRef) {
this._viewRef.destroy();
this._viewRef = undefined;
}
// Highlight and sanitize the code just in case
this.highlightedCode = this._domSanitizer.sanitize(
SecurityContext.HTML,
this._fuseHighlightService.highlight(this.code, this.lang)
);
// Return if the highlighted code is null
if (this.highlightedCode === null) {
return;
}
// Render and insert the template
this._viewRef = this._viewContainerRef.createEmbeddedView(
this.templateRef,
{
highlightedCode: this.highlightedCode,
lang: this.lang,
}
);
// Detect the changes
this._viewRef.detectChanges();
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FuseHighlightComponent } from '@fuse/components/highlight/highlight.component';
@NgModule({
declarations: [
FuseHighlightComponent
],
imports : [
CommonModule
],
exports : [
FuseHighlightComponent
]
})
export class FuseHighlightModule
{
}

View File

@ -0,0 +1,82 @@
import { Injectable } from '@angular/core';
import hljs from 'highlight.js';
@Injectable({
providedIn: 'root'
})
export class FuseHighlightService
{
/**
* Constructor
*/
constructor()
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Highlight
*/
highlight(code: string, language: string): string
{
// Format the code
code = this._format(code);
// Highlight and return the code
return hljs.highlight(code, {language}).value;
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Remove the empty lines around the code block
* and re-align the indentation based on the first
* non-whitespace indented character
*
* @param code
* @private
*/
private _format(code: string): string
{
let indentation = 0;
// Split the code into lines and store the lines
const lines = code.split('\n');
// Trim the empty lines around the code block
while ( lines.length && lines[0].trim() === '' )
{
lines.shift();
}
while ( lines.length && lines[lines.length - 1].trim() === '' )
{
lines.pop();
}
// Iterate through the lines
lines.filter(line => line.length)
.forEach((line, index) => {
// Always get the indentation of the first line so we can
// have something to compare with
if ( index === 0 )
{
indentation = line.search(/\S|$/);
return;
}
// Look at all the remaining lines to figure out the smallest indentation.
indentation = Math.min(line.search(/\S|$/), indentation);
});
// Iterate through the lines one more time, remove the extra
// indentation, join them together and return it
return lines.map(line => line.substring(indentation)).join('\n');
}
}

View File

@ -0,0 +1 @@
export * from '@fuse/components/highlight/public-api';

View File

@ -0,0 +1,3 @@
export * from '@fuse/components/highlight/highlight.component';
export * from '@fuse/components/highlight/highlight.module';
export * from '@fuse/components/highlight/highlight.service';

View File

@ -0,0 +1 @@
export * from '@fuse/components/loading-bar/public-api';

View File

@ -0,0 +1,3 @@
<ng-container *ngIf="show && !!mode">
<mat-progress-bar [mode]="mode" [value]="progress"></mat-progress-bar>
</ng-container>

View File

@ -0,0 +1,7 @@
fuse-loading-bar {
position: fixed;
top: 0;
z-index: 999;
width: 100%;
height: 6px;
}

View File

@ -0,0 +1,84 @@
import {
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Subject, takeUntil } from 'rxjs';
import { FuseLoadingService } from '@fuse/services/loading';
@Component({
selector: 'fuse-loading-bar',
templateUrl: './loading-bar.component.html',
styleUrls: ['./loading-bar.component.scss'],
encapsulation: ViewEncapsulation.None,
exportAs: 'fuseLoadingBar',
})
export class FuseLoadingBarComponent implements OnChanges, OnInit, OnDestroy {
@Input() autoMode: boolean = true;
mode?: 'determinate' | 'indeterminate';
progress: number = 0;
show: boolean = false;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(private _fuseLoadingService: FuseLoadingService) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Auto mode
if ('autoMode' in changes) {
// Set the auto mode in the service
this._fuseLoadingService.setAutoMode(
coerceBooleanProperty(changes['autoMode'].currentValue)
);
}
}
/**
* On init
*/
ngOnInit(): void {
// Subscribe to the service
this._fuseLoadingService.mode$
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((value) => {
this.mode = value;
});
this._fuseLoadingService.progress$
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((value) => {
this.progress = value;
});
this._fuseLoadingService.show$
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((value) => {
this.show = value;
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { FuseLoadingBarComponent } from '@fuse/components/loading-bar/loading-bar.component';
@NgModule({
declarations: [
FuseLoadingBarComponent
],
imports : [
CommonModule,
MatProgressBarModule
],
exports : [
FuseLoadingBarComponent
]
})
export class FuseLoadingBarModule
{
}

View File

@ -0,0 +1,2 @@
export * from '@fuse/components/loading-bar/loading-bar.component';
export * from '@fuse/components/loading-bar/loading-bar.module';

View File

@ -0,0 +1 @@
export * from '@fuse/components/masonry/public-api';

View File

@ -0,0 +1,3 @@
<div class="flex">
<ng-container *ngTemplateOutlet="columnsTemplate; context: { $implicit: distributedColumns }"></ng-container>
</div>

View File

@ -0,0 +1,86 @@
import { AfterViewInit, Component, Input, OnChanges, SimpleChanges, TemplateRef, ViewEncapsulation } from '@angular/core';
import { fuseAnimations } from '@fuse/animations';
import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
@Component({
selector : 'fuse-masonry',
templateUrl : './masonry.component.html',
encapsulation: ViewEncapsulation.None,
animations : fuseAnimations,
exportAs : 'fuseMasonry'
})
export class FuseMasonryComponent implements OnChanges, AfterViewInit
{
@Input() columnsTemplate: TemplateRef<any>;
@Input() columns: number;
@Input() items: any[] = [];
distributedColumns: any[] = [];
/**
* Constructor
*/
constructor(private _fuseMediaWatcherService: FuseMediaWatcherService)
{
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void
{
// Columns
if ( 'columns' in changes )
{
// Distribute the items
this._distributeItems();
}
// Items
if ( 'items' in changes )
{
// Distribute the items
this._distributeItems();
}
}
/**
* After view init
*/
ngAfterViewInit(): void
{
// Distribute the items for the first time
this._distributeItems();
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Distribute items into columns
*/
private _distributeItems(): void
{
// Return an empty array if there are no items
if ( this.items.length === 0 )
{
this.distributedColumns = [];
return;
}
// Prepare the distributed columns array
this.distributedColumns = Array.from(Array(this.columns), item => ({items: []}));
// Distribute the items to columns
for ( let i = 0; i < this.items.length; i++ )
{
this.distributedColumns[i % this.columns].items.push(this.items[i]);
}
}
}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FuseMasonryComponent } from '@fuse/components/masonry/masonry.component';
@NgModule({
declarations: [
FuseMasonryComponent
],
imports : [
CommonModule
],
exports : [
FuseMasonryComponent
]
})
export class FuseMasonryModule
{
}

View File

@ -0,0 +1,2 @@
export * from '@fuse/components/masonry/masonry.component';
export * from '@fuse/components/masonry/masonry.module';

View File

@ -0,0 +1,177 @@
<!-- Item wrapper -->
<div
class="fuse-horizontal-navigation-item-wrapper"
[class.fuse-horizontal-navigation-item-has-subtitle]="!!item?.subtitle"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
>
<!-- Item with an internal link -->
<ng-container
*ngIf="
item?.link && !item?.externalLink && !item?.function && !item?.disabled
"
>
<div
class="fuse-horizontal-navigation-item"
[ngClass]="{
'fuse-horizontal-navigation-item-active-forced': item?.active
}"
[routerLink]="[item?.link]"
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item with an external link -->
<ng-container
*ngIf="
item?.link && item?.externalLink && !item?.function && !item?.disabled
"
>
<a
class="fuse-horizontal-navigation-item"
[href]="item?.link"
[target]="item?.target || '_self'"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with a function -->
<ng-container *ngIf="!item?.link && item?.function && !item?.disabled">
<div
class="fuse-horizontal-navigation-item"
[ngClass]="{
'fuse-horizontal-navigation-item-active-forced': item?.active
}"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item with an internal link and function -->
<ng-container
*ngIf="
item?.link && !item?.externalLink && item?.function && !item?.disabled
"
>
<div
class="fuse-horizontal-navigation-item"
[ngClass]="{
'fuse-horizontal-navigation-item-active-forced': item?.active
}"
[routerLink]="[item?.link]"
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item with an external link and function -->
<ng-container
*ngIf="
item?.link && item?.externalLink && item?.function && !item?.disabled
"
>
<a
class="fuse-horizontal-navigation-item"
[href]="item?.link"
[target]="item?.target || '_self'"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
mat-menu-item
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with a no link and no function -->
<ng-container *ngIf="!item?.link && !item?.function && !item?.disabled">
<div
class="fuse-horizontal-navigation-item"
[ngClass]="{
'fuse-horizontal-navigation-item-active-forced': item?.active
}"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item is disabled -->
<ng-container *ngIf="item?.disabled">
<div
class="fuse-horizontal-navigation-item fuse-horizontal-navigation-item-disabled"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
</div>
<!-- Item template -->
<ng-template #itemTemplate>
<!-- Icon -->
<ng-container *ngIf="item?.icon">
<mat-icon
class="fuse-horizontal-navigation-item-icon"
[ngClass]="
!!item && !!item.classes && !!item.classes.icon ? item.classes.icon : ''
"
[svgIcon]="!!item && !!item.icon ? item.icon : ''"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-horizontal-navigation-item-title-wrapper">
<div class="fuse-horizontal-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title ? item.classes.title : ''
"
>
{{ item?.title }}
</span>
</div>
<ng-container *ngIf="item?.subtitle">
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
<span
[ngClass]="
!!item && item.classes && item.classes.subtitle
? item.classes.subtitle
: ''
"
>
{{ item?.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item?.badge">
<div class="fuse-horizontal-navigation-item-badge">
<div
class="fuse-horizontal-navigation-item-badge-content"
[ngClass]="
!!item && !!item.badge && !!item.badge.classes
? item.badge.classes
: ''
"
>
{{ item?.badge?.title }}
</div>
</div>
</ng-container>
</ng-template>

View File

@ -0,0 +1,86 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { IsActiveMatchOptions } from '@angular/router';
import { Subject, takeUntil } from 'rxjs';
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
@Component({
selector: 'fuse-horizontal-navigation-basic-item',
templateUrl: './basic.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseHorizontalNavigationBasicItemComponent
implements OnInit, OnDestroy
{
@Input() item?: FuseNavigationItem;
@Input() name?: string;
isActiveMatchOptions: IsActiveMatchOptions;
private _fuseHorizontalNavigationComponent?: FuseHorizontalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService,
private _fuseUtilsService: FuseUtilsService
) {
// Set the equivalent of {exact: false} as default for active match options.
// We are not assigning the item.isActiveMatchOptions directly to the
// [routerLinkActiveOptions] because if it's "undefined" initially, the router
// will throw an error and stop working.
this.isActiveMatchOptions = this._fuseUtilsService.subsetMatchOptions;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Set the "isActiveMatchOptions" either from item's
// "isActiveMatchOptions" or the equivalent form of
// item's "exactMatch" option
this.isActiveMatchOptions =
this.item?.isActiveMatchOptions ?? this.item?.exactMatch
? this._fuseUtilsService.exactMatchOptions
: this._fuseUtilsService.subsetMatchOptions;
// Get the parent navigation component
this._fuseHorizontalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Mark for check
this._changeDetectorRef.markForCheck();
// Subscribe to onRefreshed on the navigation component
this._fuseHorizontalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,138 @@
<ng-container *ngIf="!child">
<div
[ngClass]="{
'fuse-horizontal-navigation-menu-active': trigger.menuOpen,
'fuse-horizontal-navigation-menu-active-forced': item?.active
}"
[matMenuTriggerFor]="matMenu"
(onMenuOpen)="triggerChangeDetection()"
(onMenuClose)="triggerChangeDetection()"
#trigger="matMenuTrigger"
>
<ng-container
*ngTemplateOutlet="itemTemplate; context: { $implicit: item }"
></ng-container>
</div>
</ng-container>
<mat-menu
class="fuse-horizontal-navigation-menu-panel"
[overlapTrigger]="false"
#matMenu="matMenu"
>
<ng-container *ngFor="let item of item?.children; trackBy: trackByFn">
<!-- Skip the hidden items -->
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
<!-- Basic -->
<ng-container *ngIf="item.type === 'basic'">
<div
class="fuse-horizontal-navigation-menu-item"
[disabled]="item.disabled"
mat-menu-item
>
<fuse-horizontal-navigation-basic-item
[item]="item"
[name]="name"
></fuse-horizontal-navigation-basic-item>
</div>
</ng-container>
<!-- Branch: aside, collapsable, group -->
<ng-container
*ngIf="
item.type === 'aside' ||
item.type === 'collapsable' ||
item.type === 'group'
"
>
<div
class="fuse-horizontal-navigation-menu-item"
[disabled]="item.disabled"
[matMenuTriggerFor]="branch.matMenu"
mat-menu-item
>
<ng-container
*ngTemplateOutlet="itemTemplate; context: { $implicit: item }"
></ng-container>
<fuse-horizontal-navigation-branch-item
[child]="true"
[item]="item"
[name]="name"
#branch
></fuse-horizontal-navigation-branch-item>
</div>
</ng-container>
<!-- Divider -->
<ng-container *ngIf="item.type === 'divider'">
<div class="fuse-horizontal-navigation-menu-item" mat-menu-item>
<fuse-horizontal-navigation-divider-item
[item]="item"
[name]="name"
></fuse-horizontal-navigation-divider-item>
</div>
</ng-container>
</ng-container>
</ng-container>
</mat-menu>
<!-- Item template -->
<ng-template let-item #itemTemplate>
<div
class="fuse-horizontal-navigation-item-wrapper"
[class.fuse-horizontal-navigation-item-has-subtitle]="!!item.subtitle"
[ngClass]="item.classes?.wrapper"
>
<div
class="fuse-horizontal-navigation-item"
[ngClass]="{
'fuse-horizontal-navigation-item-disabled': item.disabled,
'fuse-horizontal-navigation-item-active-forced': item.active
}"
[matTooltip]="item.tooltip || ''"
>
<!-- Icon -->
<ng-container *ngIf="item.icon">
<mat-icon
class="fuse-horizontal-navigation-item-icon"
[ngClass]="item.classes?.icon"
[svgIcon]="item.icon"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-horizontal-navigation-item-title-wrapper">
<div class="fuse-horizontal-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title
? item.classes.title
: ''
"
>
{{ item.title }}
</span>
</div>
<ng-container *ngIf="item.subtitle">
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
<span [ngClass]="item.classes?.subtitle">
{{ item.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item.badge">
<div class="fuse-horizontal-navigation-item-badge">
<div
class="fuse-horizontal-navigation-item-badge-content"
[ngClass]="item.badge.classes"
>
{{ item.badge.title }}
</div>
</div>
</ng-container>
</div>
</div>
</ng-template>

View File

@ -0,0 +1,96 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
ViewChild,
} from '@angular/core';
import { BooleanInput } from '@angular/cdk/coercion';
import { MatMenu } from '@angular/material/menu';
import { Subject, takeUntil } from 'rxjs';
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-horizontal-navigation-branch-item',
templateUrl: './branch.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseHorizontalNavigationBranchItemComponent
implements OnInit, OnDestroy
{
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_child: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() child: boolean = false;
@Input() item?: FuseNavigationItem;
@Input() name?: string;
@ViewChild('matMenu', { static: true }) matMenu!: MatMenu;
private _fuseHorizontalNavigationComponent?: FuseHorizontalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseHorizontalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseHorizontalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Trigger the change detection
*/
triggerChangeDetection(): void {
// Mark for check
this._changeDetectorRef.markForCheck();
}
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any {
return item.id || index;
}
}

View File

@ -0,0 +1,9 @@
<!-- Divider -->
<div
class="fuse-horizontal-navigation-item-wrapper divider"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
></div>

View File

@ -0,0 +1,65 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-horizontal-navigation-divider-item',
templateUrl: './divider.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseHorizontalNavigationDividerItemComponent
implements OnInit, OnDestroy
{
@Input() item?: FuseNavigationItem;
@Input() name?: string;
private _fuseHorizontalNavigationComponent?: FuseHorizontalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseHorizontalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseHorizontalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,9 @@
<!-- Spacer -->
<div
class="fuse-horizontal-navigation-item-wrapper"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
></div>

View File

@ -0,0 +1,65 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-horizontal-navigation-spacer-item',
templateUrl: './spacer.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseHorizontalNavigationSpacerItemComponent
implements OnInit, OnDestroy
{
@Input() item?: FuseNavigationItem;
@Input() name?: string;
private _fuseHorizontalNavigationComponent?: FuseHorizontalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseHorizontalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseHorizontalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,36 @@
<div class="fuse-horizontal-navigation-wrapper">
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
<!-- Skip the hidden items -->
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
<!-- Basic -->
<ng-container *ngIf="item.type === 'basic'">
<fuse-horizontal-navigation-basic-item
class="fuse-horizontal-navigation-menu-item"
[item]="item"
[name]="name"></fuse-horizontal-navigation-basic-item>
</ng-container>
<!-- Branch: aside, collapsable, group -->
<ng-container *ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'">
<fuse-horizontal-navigation-branch-item
class="fuse-horizontal-navigation-menu-item"
[item]="item"
[name]="name"></fuse-horizontal-navigation-branch-item>
</ng-container>
<!-- Spacer -->
<ng-container *ngIf="item.type === 'spacer'">
<fuse-horizontal-navigation-spacer-item
class="fuse-horizontal-navigation-menu-item"
[item]="item"
[name]="name"></fuse-horizontal-navigation-spacer-item>
</ng-container>
</ng-container>
</ng-container>
</div>

View File

@ -0,0 +1,180 @@
/* Root navigation specific */
fuse-horizontal-navigation {
.fuse-horizontal-navigation-wrapper {
display: flex;
align-items: center;
/* Basic, Branch */
fuse-horizontal-navigation-basic-item,
fuse-horizontal-navigation-branch-item {
@screen sm {
&:hover {
.fuse-horizontal-navigation-item-wrapper {
@apply bg-hover;
}
}
}
.fuse-horizontal-navigation-item-wrapper {
border-radius: 4px;
overflow: hidden;
.fuse-horizontal-navigation-item {
padding: 0 16px;
cursor: pointer;
user-select: none;
.fuse-horizontal-navigation-item-icon {
margin-right: 12px;
}
}
}
}
/* Basic - When item active (current link) */
fuse-horizontal-navigation-basic-item {
.fuse-horizontal-navigation-item-active,
.fuse-horizontal-navigation-item-active-forced {
.fuse-horizontal-navigation-item-title {
@apply text-primary #{'!important'};
}
.fuse-horizontal-navigation-item-subtitle {
@apply text-primary-400 #{'!important'};
.dark & {
@apply text-primary-600 #{'!important'};
}
}
.fuse-horizontal-navigation-item-icon {
@apply text-primary #{'!important'};
}
}
}
/* Branch - When menu open */
fuse-horizontal-navigation-branch-item {
.fuse-horizontal-navigation-menu-active,
.fuse-horizontal-navigation-menu-active-forced {
.fuse-horizontal-navigation-item-wrapper {
@apply bg-hover;
}
}
}
/* Spacer */
fuse-horizontal-navigation-spacer-item {
margin: 12px 0;
}
}
}
/* Menu panel specific */
.fuse-horizontal-navigation-menu-panel {
.fuse-horizontal-navigation-menu-item {
height: auto;
min-height: 0;
line-height: normal;
white-space: normal;
/* Basic, Branch */
fuse-horizontal-navigation-basic-item,
fuse-horizontal-navigation-branch-item,
fuse-horizontal-navigation-divider-item {
display: flex;
flex: 1 1 auto;
}
/* Divider */
fuse-horizontal-navigation-divider-item {
margin: 8px -16px;
.fuse-horizontal-navigation-item-wrapper {
height: 1px;
box-shadow: 0 1px 0 0;
}
}
}
}
/* Navigation menu item common */
.fuse-horizontal-navigation-menu-item {
/* Basic - When item active (current link) */
fuse-horizontal-navigation-basic-item {
.fuse-horizontal-navigation-item-active,
.fuse-horizontal-navigation-item-active-forced {
.fuse-horizontal-navigation-item-title {
@apply text-primary #{'!important'};
}
.fuse-horizontal-navigation-item-subtitle {
@apply text-primary-400 #{'!important'};
.dark & {
@apply text-primary-600 #{'!important'};
}
}
.fuse-horizontal-navigation-item-icon {
@apply text-primary #{'!important'};
}
}
}
.fuse-horizontal-navigation-item-wrapper {
width: 100%;
&.fuse-horizontal-navigation-item-has-subtitle {
.fuse-horizontal-navigation-item {
min-height: 56px;
}
}
.fuse-horizontal-navigation-item {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 48px;
width: 100%;
font-size: 13px;
font-weight: 500;
text-decoration: none;
.fuse-horizontal-navigation-item-title-wrapper {
.fuse-horizontal-navigation-item-subtitle {
font-size: 12px;
}
}
.fuse-horizontal-navigation-item-badge {
margin-left: auto;
.fuse-horizontal-navigation-item-badge-content {
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: 600;
white-space: nowrap;
height: 20px;
}
}
}
}
}

View File

@ -0,0 +1,111 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
ViewEncapsulation,
} from '@angular/core';
import { ReplaySubject, Subject } from 'rxjs';
import { fuseAnimations } from '@fuse/animations';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
@Component({
selector: 'fuse-horizontal-navigation',
templateUrl: './horizontal.component.html',
styleUrls: ['./horizontal.component.scss'],
animations: fuseAnimations,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
exportAs: 'fuseHorizontalNavigation',
})
export class FuseHorizontalNavigationComponent
implements OnChanges, OnInit, OnDestroy
{
@Input() name: string = this._fuseUtilsService.randomId();
@Input() navigation?: FuseNavigationItem[];
onRefreshed: ReplaySubject<boolean> = new ReplaySubject<boolean>(1);
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService,
private _fuseUtilsService: FuseUtilsService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Navigation
if ('navigation' in changes) {
// Mark for check
this._changeDetectorRef.markForCheck();
}
}
/**
* On init
*/
ngOnInit(): void {
// Make sure the name input is not an empty string
if (this.name === '') {
this.name = this._fuseUtilsService.randomId();
}
// Register the navigation component
this._fuseNavigationService.registerComponent(this.name, this);
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Deregister the navigation component from the registry
this._fuseNavigationService.deregisterComponent(this.name);
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Refresh the component to apply the changes
*/
refresh(): void {
// Mark for check
this._changeDetectorRef.markForCheck();
// Execute the observable
this.onRefreshed.next(true);
}
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any {
return item.id || index;
}
}

View File

@ -0,0 +1 @@
export * from '@fuse/components/navigation/public-api';

View File

@ -0,0 +1,55 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatTooltipModule } from '@angular/material/tooltip';
import { FuseScrollbarModule } from '@fuse/directives/scrollbar/public-api';
import { FuseHorizontalNavigationBasicItemComponent } from '@fuse/components/navigation/horizontal/components/basic/basic.component';
import { FuseHorizontalNavigationBranchItemComponent } from '@fuse/components/navigation/horizontal/components/branch/branch.component';
import { FuseHorizontalNavigationDividerItemComponent } from '@fuse/components/navigation/horizontal/components/divider/divider.component';
import { FuseHorizontalNavigationSpacerItemComponent } from '@fuse/components/navigation/horizontal/components/spacer/spacer.component';
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
import { FuseVerticalNavigationAsideItemComponent } from '@fuse/components/navigation/vertical/components/aside/aside.component';
import { FuseVerticalNavigationBasicItemComponent } from '@fuse/components/navigation/vertical/components/basic/basic.component';
import { FuseVerticalNavigationCollapsableItemComponent } from '@fuse/components/navigation/vertical/components/collapsable/collapsable.component';
import { FuseVerticalNavigationDividerItemComponent } from '@fuse/components/navigation/vertical/components/divider/divider.component';
import { FuseVerticalNavigationGroupItemComponent } from '@fuse/components/navigation/vertical/components/group/group.component';
import { FuseVerticalNavigationSpacerItemComponent } from '@fuse/components/navigation/vertical/components/spacer/spacer.component';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
@NgModule({
declarations: [
FuseHorizontalNavigationBasicItemComponent,
FuseHorizontalNavigationBranchItemComponent,
FuseHorizontalNavigationDividerItemComponent,
FuseHorizontalNavigationSpacerItemComponent,
FuseHorizontalNavigationComponent,
FuseVerticalNavigationAsideItemComponent,
FuseVerticalNavigationBasicItemComponent,
FuseVerticalNavigationCollapsableItemComponent,
FuseVerticalNavigationDividerItemComponent,
FuseVerticalNavigationGroupItemComponent,
FuseVerticalNavigationSpacerItemComponent,
FuseVerticalNavigationComponent
],
imports : [
CommonModule,
RouterModule,
MatButtonModule,
MatDividerModule,
MatIconModule,
MatMenuModule,
MatTooltipModule,
FuseScrollbarModule
],
exports : [
FuseHorizontalNavigationComponent,
FuseVerticalNavigationComponent
]
})
export class FuseNavigationModule
{
}

View File

@ -0,0 +1,182 @@
import { Injectable } from '@angular/core';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Injectable({
providedIn: 'root',
})
export class FuseNavigationService {
private _componentRegistry: Map<string, any> = new Map<string, any>();
private _navigationStore: Map<string, FuseNavigationItem[]> = new Map<
string,
any
>();
/**
* Constructor
*/
constructor() {}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Register navigation component
*
* @param name
* @param component
*/
registerComponent(name: string, component: any): void {
this._componentRegistry.set(name, component);
}
/**
* Deregister navigation component
*
* @param name
*/
deregisterComponent(name: string): void {
this._componentRegistry.delete(name);
}
/**
* Get navigation component from the registry
*
* @param name
*/
getComponent<T>(name?: string): T | undefined {
if (!name) {
return undefined;
}
return this._componentRegistry.get(name);
}
/**
* Store the given navigation with the given key
*
* @param key
* @param navigation
*/
storeNavigation(key: string, navigation: FuseNavigationItem[]): void {
// Add to the store
this._navigationStore.set(key, navigation);
}
/**
* Get navigation from storage by key
*
* @param key
*/
getNavigation(key: string): FuseNavigationItem[] {
return this._navigationStore.get(key) ?? [];
}
/**
* Delete the navigation from the storage
*
* @param key
*/
deleteNavigation(key: string): void {
// Check if the navigation exists
if (!this._navigationStore.has(key)) {
console.warn(
`Navigation with the key '${key}' does not exist in the store.`
);
}
// Delete from the storage
this._navigationStore.delete(key);
}
/**
* Utility function that returns a flattened
* version of the given navigation array
*
* @param navigation
* @param flatNavigation
*/
getFlatNavigation(
navigation: FuseNavigationItem[],
flatNavigation: FuseNavigationItem[] = []
): FuseNavigationItem[] {
for (const item of navigation) {
if (item.type === 'basic') {
flatNavigation.push(item);
continue;
}
if (
item.type === 'aside' ||
item.type === 'collapsable' ||
item.type === 'group'
) {
if (item.children) {
this.getFlatNavigation(item.children, flatNavigation);
}
}
}
return flatNavigation;
}
/**
* Utility function that returns the item
* with the given id from given navigation
*
* @param id
* @param navigation
*/
getItem(
navigation: FuseNavigationItem[],
id?: string
): FuseNavigationItem | null {
if (!id) {
return null;
}
for (const item of navigation) {
if (item.id === id) {
return item;
}
if (item.children) {
const childItem = this.getItem(item.children, id);
if (childItem) {
return childItem;
}
}
}
return null;
}
/**
* Utility function that returns the item's parent
* with the given id from given navigation
*
* @param id
* @param navigation
* @param parent
*/
getItemParent(
id: string,
navigation: FuseNavigationItem[],
parent: FuseNavigationItem[] | FuseNavigationItem
): FuseNavigationItem[] | FuseNavigationItem | null {
for (const item of navigation) {
if (item.id === id) {
return parent;
}
if (item.children) {
const childItem = this.getItemParent(id, item.children, item);
if (childItem) {
return childItem;
}
}
}
return null;
}
}

View File

@ -0,0 +1,41 @@
import { IsActiveMatchOptions } from '@angular/router';
export interface FuseNavigationItem {
id?: string;
title?: string;
subtitle?: string;
type: 'aside' | 'basic' | 'collapsable' | 'divider' | 'group' | 'spacer';
hidden?: (item: FuseNavigationItem) => boolean;
active?: boolean;
disabled?: boolean;
tooltip?: string;
link?: string;
externalLink?: boolean;
target?: '_blank' | '_self' | '_parent' | '_top' | string;
exactMatch?: boolean;
isActiveMatchOptions?: IsActiveMatchOptions;
function?: (item?: FuseNavigationItem) => void;
classes?: {
title?: string;
subtitle?: string;
icon?: string;
wrapper?: string;
};
icon?: string;
badge?: {
title?: string;
classes?: string;
};
children?: FuseNavigationItem[];
meta?: any;
}
export type FuseVerticalNavigationAppearance =
| 'default'
| 'compact'
| 'dense'
| 'thin';
export type FuseVerticalNavigationMode = 'over' | 'side';
export type FuseVerticalNavigationPosition = 'left' | 'right';

View File

@ -0,0 +1,5 @@
export * from '@fuse/components/navigation/horizontal/horizontal.component';
export * from '@fuse/components/navigation/vertical/vertical.component';
export * from '@fuse/components/navigation/navigation.module';
export * from '@fuse/components/navigation/navigation.service';
export * from '@fuse/components/navigation/navigation.types';

View File

@ -0,0 +1,126 @@
<div
class="fuse-vertical-navigation-item-wrapper"
[class.fuse-vertical-navigation-item-has-subtitle]="!!item?.subtitle"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
>
<div
class="fuse-vertical-navigation-item"
[ngClass]="{
'fuse-vertical-navigation-item-active': active,
'fuse-vertical-navigation-item-disabled': item?.disabled,
'fuse-vertical-navigation-item-active-forced': item?.active
}"
[matTooltip]="item?.tooltip || ''"
>
<!-- Icon -->
<ng-container *ngIf="item?.icon">
<mat-icon
class="fuse-vertical-navigation-item-icon"
[ngClass]="
!!item && !!item.classes && !!item.classes.icon
? item.classes.icon
: ''
"
[svgIcon]="!!item && !!item.icon ? item.icon : ''"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-vertical-navigation-item-title-wrapper">
<div class="fuse-vertical-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title
? item.classes.title
: ''
"
>
{{ item?.title }}
</span>
</div>
<ng-container *ngIf="item?.subtitle">
<div class="fuse-vertical-navigation-item-subtitle">
<span
[ngClass]="
!!item && !!item.classes && !!item.classes.subtitle
? item.classes.subtitle
: ''
"
>
{{ item?.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item?.badge">
<div class="fuse-vertical-navigation-item-badge">
<div
class="fuse-vertical-navigation-item-badge-content"
[ngClass]="
!!item && !!item.badge && !!item.badge.classes
? item.badge.classes
: ''
"
>
{{ item?.badge?.title }}
</div>
</div>
</ng-container>
</div>
</div>
<ng-container *ngIf="!skipChildren">
<div class="fuse-vertical-navigation-item-children">
<ng-container *ngFor="let item of item?.children; trackBy: trackByFn">
<!-- Skip the hidden items -->
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
<!-- Basic -->
<ng-container *ngIf="item.type === 'basic'">
<fuse-vertical-navigation-basic-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-basic-item>
</ng-container>
<!-- Collapsable -->
<ng-container *ngIf="item.type === 'collapsable'">
<fuse-vertical-navigation-collapsable-item
[item]="item"
[name]="name"
[autoCollapse]="autoCollapse"
></fuse-vertical-navigation-collapsable-item>
</ng-container>
<!-- Divider -->
<ng-container *ngIf="item.type === 'divider'">
<fuse-vertical-navigation-divider-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-divider-item>
</ng-container>
<!-- Group -->
<ng-container *ngIf="item.type === 'group'">
<fuse-vertical-navigation-group-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-group-item>
</ng-container>
<!-- Spacer -->
<ng-container *ngIf="item.type === 'spacer'">
<fuse-vertical-navigation-spacer-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-spacer-item>
</ng-container>
</ng-container>
</ng-container>
</div>
</ng-container>

View File

@ -0,0 +1,187 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnChanges,
OnDestroy,
OnInit,
SimpleChanges,
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { BooleanInput } from '@angular/cdk/coercion';
import { filter, Subject, takeUntil } from 'rxjs';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-vertical-navigation-aside-item',
templateUrl: './aside.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseVerticalNavigationAsideItemComponent
implements OnChanges, OnInit, OnDestroy
{
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_autoCollapse: BooleanInput;
static ngAcceptInputType_skipChildren: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() activeItemId?: string;
@Input() autoCollapse?: boolean;
@Input() item!: FuseNavigationItem;
@Input() name?: string;
@Input() skipChildren?: boolean;
active: boolean = false;
private _fuseVerticalNavigationComponent?: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _router: Router,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On changes
*
* @param changes
*/
ngOnChanges(changes: SimpleChanges): void {
// Active item id
if ('activeItemId' in changes) {
// Mark if active
this._markIfActive(this._router.url);
}
}
/**
* On init
*/
ngOnInit(): void {
// Mark if active
this._markIfActive(this._router.url);
// Attach a listener to the NavigationEnd event
this._router.events
.pipe(
filter(
(event): event is NavigationEnd => event instanceof NavigationEnd
),
takeUntil(this._unsubscribeAll)
)
.subscribe((event: NavigationEnd) => {
// Mark if active
this._markIfActive(event.urlAfterRedirects);
});
// Get the parent navigation component
this._fuseVerticalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any {
return item.id || index;
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Check if the given item has the given url
* in one of its children
*
* @param item
* @param currentUrl
* @private
*/
private _hasActiveChild(
item: FuseNavigationItem,
currentUrl: string
): boolean {
const children = item.children;
if (!children) {
return false;
}
for (const child of children) {
if (child.children) {
if (this._hasActiveChild(child, currentUrl)) {
return true;
}
}
// Skip items other than 'basic'
if (child.type !== 'basic') {
continue;
}
// Check if the child has a link and is active
if (
child.link &&
this._router.isActive(child.link, child.exactMatch || false)
) {
return true;
}
}
return false;
}
/**
* Decide and mark if the item is active
*
* @private
*/
private _markIfActive(currentUrl: string): void {
// Check if the activeItemId is equals to this item id
this.active = this.activeItemId === this.item?.id;
// If the aside has a children that is active,
// always mark it as active
if (this._hasActiveChild(this.item, currentUrl)) {
this.active = true;
}
// Mark for check
this._changeDetectorRef.markForCheck();
}
}

View File

@ -0,0 +1,177 @@
<!-- Item wrapper -->
<div
class="fuse-vertical-navigation-item-wrapper"
[class.fuse-vertical-navigation-item-has-subtitle]="!!item?.subtitle"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
>
<!-- Item with an internal link -->
<ng-container
*ngIf="
item?.link && !item?.externalLink && !item?.function && !item?.disabled
"
>
<a
class="fuse-vertical-navigation-item"
[ngClass]="{
'fuse-vertical-navigation-item-active-forced': item?.active
}"
[routerLink]="[item?.link]"
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with an external link -->
<ng-container
*ngIf="
item?.link && item?.externalLink && !item?.function && !item?.disabled
"
>
<a
class="fuse-vertical-navigation-item"
[href]="item?.link"
[target]="item?.target || '_self'"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with a function -->
<ng-container *ngIf="!item?.link && item?.function && !item?.disabled">
<div
class="fuse-vertical-navigation-item"
[ngClass]="{
'fuse-vertical-navigation-item-active-forced': item?.active
}"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item with an internal link and function -->
<ng-container
*ngIf="
item?.link && !item?.externalLink && item?.function && !item?.disabled
"
>
<a
class="fuse-vertical-navigation-item"
[ngClass]="{
'fuse-vertical-navigation-item-active-forced': item?.active
}"
[routerLink]="[item?.link]"
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
[routerLinkActiveOptions]="isActiveMatchOptions"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with an external link and function -->
<ng-container
*ngIf="
item?.link && item?.externalLink && item?.function && !item?.disabled
"
>
<a
class="fuse-vertical-navigation-item"
[href]="item?.link"
[target]="item?.target || '_self'"
[matTooltip]="item?.tooltip || ''"
(click)="item?.function(item)"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</a>
</ng-container>
<!-- Item with a no link and no function -->
<ng-container *ngIf="!item?.link && !item?.function && !item?.disabled">
<div
class="fuse-vertical-navigation-item"
[ngClass]="{
'fuse-vertical-navigation-item-active-forced': item?.active
}"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
<!-- Item is disabled -->
<ng-container *ngIf="item?.disabled">
<div
class="fuse-vertical-navigation-item fuse-vertical-navigation-item-disabled"
[matTooltip]="item?.tooltip || ''"
>
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
</div>
</ng-container>
</div>
<!-- Item template -->
<ng-template #itemTemplate>
<!-- Icon -->
<ng-container *ngIf="item?.icon">
<mat-icon
class="fuse-vertical-navigation-item-icon"
[ngClass]="
!!item && !!item.classes && !!item.classes.icon ? item.classes.icon : ''
"
[svgIcon]="!!item && !!item.icon ? item.icon : ''"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-vertical-navigation-item-title-wrapper">
<div class="fuse-vertical-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title ? item.classes.title : ''
"
>
{{ item?.title }}
</span>
</div>
<ng-container *ngIf="item?.subtitle">
<div class="fuse-vertical-navigation-item-subtitle">
<span
[ngClass]="
!!item && !!item.classes && !!item.classes.subtitle
? item.classes.subtitle
: ''
"
>
{{ item?.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item?.badge">
<div class="fuse-vertical-navigation-item-badge">
<div
class="fuse-vertical-navigation-item-badge-content"
[ngClass]="
!!item && !!item.badge && !!item.badge.classes
? item.badge.classes
: ''
"
>
{{ item?.badge?.title }}
</div>
</div>
</ng-container>
</ng-template>

View File

@ -0,0 +1,86 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { IsActiveMatchOptions } from '@angular/router';
import { Subject, takeUntil } from 'rxjs';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
@Component({
selector: 'fuse-vertical-navigation-basic-item',
templateUrl: './basic.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseVerticalNavigationBasicItemComponent
implements OnInit, OnDestroy
{
@Input() item?: FuseNavigationItem;
@Input() name?: string;
isActiveMatchOptions: IsActiveMatchOptions;
private _fuseVerticalNavigationComponent?: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService,
private _fuseUtilsService: FuseUtilsService
) {
// Set the equivalent of {exact: false} as default for active match options.
// We are not assigning the item.isActiveMatchOptions directly to the
// [routerLinkActiveOptions] because if it's "undefined" initially, the router
// will throw an error and stop working.
this.isActiveMatchOptions = this._fuseUtilsService.subsetMatchOptions;
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Set the "isActiveMatchOptions" either from item's
// "isActiveMatchOptions" or the equivalent form of
// item's "exactMatch" option
this.isActiveMatchOptions =
this.item?.isActiveMatchOptions ?? this.item?.exactMatch
? this._fuseUtilsService.exactMatchOptions
: this._fuseUtilsService.subsetMatchOptions;
// Get the parent navigation component
this._fuseVerticalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Mark for check
this._changeDetectorRef.markForCheck();
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,127 @@
<div
class="fuse-vertical-navigation-item-wrapper"
[class.fuse-vertical-navigation-item-has-subtitle]="!!item?.subtitle"
[ngClass]="
!!item && !!item.classes && item.classes.wrapper ? item.classes.wrapper : ''
"
>
<div
class="fuse-vertical-navigation-item"
[ngClass]="{ 'fuse-vertical-navigation-item-disabled': item?.disabled }"
[matTooltip]="item?.tooltip || ''"
(click)="toggleCollapsable()"
>
<!-- Icon -->
<ng-container *ngIf="item?.icon">
<mat-icon
class="fuse-vertical-navigation-item-icon"
[ngClass]="
!!item && !!item.classes && item.classes.icon ? item.classes.icon : ''
"
[svgIcon]="!!item && !!item.icon ? item.icon : ''"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-vertical-navigation-item-title-wrapper">
<div class="fuse-vertical-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title
? item.classes.title
: ''
"
>
{{ item?.title }}
</span>
</div>
<ng-container *ngIf="item?.subtitle">
<div class="fuse-vertical-navigation-item-subtitle">
<span
[ngClass]="
!!item && !!item.classes && !!item.classes.subtitle
? item.classes.subtitle
: ''
"
>
{{ item?.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item?.badge">
<div class="fuse-vertical-navigation-item-badge">
<div
class="fuse-vertical-navigation-item-badge-content"
[ngClass]="
!!item && !!item.badge && !!item.badge.classes
? item.badge.classes
: ''
"
>
{{ item?.badge?.title }}
</div>
</div>
</ng-container>
<!-- Arrow -->
<mat-icon
class="fuse-vertical-navigation-item-arrow icon-size-4"
[svgIcon]="'heroicons_solid:chevron-right'"
></mat-icon>
</div>
</div>
<div
class="fuse-vertical-navigation-item-children"
*ngIf="!isCollapsed"
@expandCollapse
>
<ng-container *ngFor="let item of item?.children; trackBy: trackByFn">
<!-- Skip the hidden items -->
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
<!-- Basic -->
<ng-container *ngIf="item.type === 'basic'">
<fuse-vertical-navigation-basic-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-basic-item>
</ng-container>
<!-- Collapsable -->
<ng-container *ngIf="item.type === 'collapsable'">
<fuse-vertical-navigation-collapsable-item
[item]="item"
[name]="name"
[autoCollapse]="autoCollapse"
></fuse-vertical-navigation-collapsable-item>
</ng-container>
<!-- Divider -->
<ng-container *ngIf="item.type === 'divider'">
<fuse-vertical-navigation-divider-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-divider-item>
</ng-container>
<!-- Group -->
<ng-container *ngIf="item.type === 'group'">
<fuse-vertical-navigation-group-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-group-item>
</ng-container>
<!-- Spacer -->
<ng-container *ngIf="item.type === 'spacer'">
<fuse-vertical-navigation-spacer-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-spacer-item>
</ng-container>
</ng-container>
</ng-container>
</div>

View File

@ -0,0 +1,325 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
HostBinding,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { BooleanInput } from '@angular/cdk/coercion';
import { filter, Subject, takeUntil } from 'rxjs';
import { fuseAnimations } from '@fuse/animations';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-vertical-navigation-collapsable-item',
templateUrl: './collapsable.component.html',
animations: fuseAnimations,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseVerticalNavigationCollapsableItemComponent
implements OnInit, OnDestroy
{
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_autoCollapse: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() autoCollapse: boolean = true;
@Input() item!: FuseNavigationItem;
@Input() name?: string;
isCollapsed: boolean = true;
isExpanded: boolean = false;
private _fuseVerticalNavigationComponent?: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _router: Router,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Host binding for component classes
*/
@HostBinding('class') get classList(): any {
return {
'fuse-vertical-navigation-item-collapsed': this.isCollapsed,
'fuse-vertical-navigation-item-expanded': this.isExpanded,
};
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseVerticalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// If the item has a children that has a matching url with the current url, expand...
if (this._hasActiveChild(this.item, this._router.url)) {
this.expand();
}
// Otherwise...
else {
// If the autoCollapse is on, collapse...
if (this.autoCollapse) {
this.collapse();
}
}
// Listen for the onCollapsableItemCollapsed from the service
this._fuseVerticalNavigationComponent?.onCollapsableItemCollapsed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((collapsedItem) => {
// Check if the collapsed item is null
if (collapsedItem === null) {
return;
}
// Collapse if this is a children of the collapsed item
if (this._isChildrenOf(collapsedItem, this.item)) {
this.collapse();
}
});
// Listen for the onCollapsableItemExpanded from the service if the autoCollapse is on
if (this.autoCollapse) {
this._fuseVerticalNavigationComponent?.onCollapsableItemExpanded
.pipe(takeUntil(this._unsubscribeAll))
.subscribe((expandedItem) => {
// Check if the expanded item is null
if (expandedItem === null) {
return;
}
// Check if this is a parent of the expanded item
if (this._isChildrenOf(this.item, expandedItem)) {
return;
}
// Check if this has a children with a matching url with the current active url
if (this._hasActiveChild(this.item, this._router.url)) {
return;
}
// Check if this is the expanded item
if (this.item === expandedItem) {
return;
}
// If none of the above conditions are matched, collapse this item
this.collapse();
});
}
// Attach a listener to the NavigationEnd event
this._router.events
.pipe(
filter(
(event): event is NavigationEnd => event instanceof NavigationEnd
),
takeUntil(this._unsubscribeAll)
)
.subscribe((event: NavigationEnd) => {
// If the item has a children that has a matching url with the current url, expand...
if (this._hasActiveChild(this.item, event.urlAfterRedirects)) {
this.expand();
}
// Otherwise...
else {
// If the autoCollapse is on, collapse...
if (this.autoCollapse) {
this.collapse();
}
}
});
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Collapse
*/
collapse(): void {
// Return if the item is disabled
if (this.item?.disabled) {
return;
}
// Return if the item is already collapsed
if (this.isCollapsed) {
return;
}
// Collapse it
this.isCollapsed = true;
this.isExpanded = !this.isCollapsed;
// Mark for check
this._changeDetectorRef.markForCheck();
// Execute the observable
this._fuseVerticalNavigationComponent?.onCollapsableItemCollapsed.next(
this.item
);
}
/**
* Expand
*/
expand(): void {
// Return if the item is disabled
if (this.item?.disabled) {
return;
}
// Return if the item is already expanded
if (!this.isCollapsed) {
return;
}
// Expand it
this.isCollapsed = false;
this.isExpanded = !this.isCollapsed;
// Mark for check
this._changeDetectorRef.markForCheck();
// Execute the observable
this._fuseVerticalNavigationComponent?.onCollapsableItemExpanded.next(
this.item
);
}
/**
* Toggle collapsable
*/
toggleCollapsable(): void {
// Toggle collapse/expand
if (this.isCollapsed) {
this.expand();
} else {
this.collapse();
}
}
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any {
return item.id || index;
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Check if the given item has the given url
* in one of its children
*
* @param item
* @param currentUrl
* @private
*/
private _hasActiveChild(
item: FuseNavigationItem,
currentUrl: string
): boolean {
const children = item.children;
if (!children) {
return false;
}
for (const child of children) {
if (child.children) {
if (this._hasActiveChild(child, currentUrl)) {
return true;
}
}
// Check if the child has a link and is active
if (
child.link &&
this._router.isActive(child.link, child.exactMatch || false)
) {
return true;
}
}
return false;
}
/**
* Check if this is a children
* of the given item
*
* @param parent
* @param item
* @private
*/
private _isChildrenOf(
parent: FuseNavigationItem,
item: FuseNavigationItem
): boolean {
const children = parent.children;
if (!children) {
return false;
}
if (children.indexOf(item) > -1) {
return true;
}
for (const child of children) {
if (child.children) {
if (this._isChildrenOf(child, item)) {
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,9 @@
<!-- Divider -->
<div
class="fuse-vertical-navigation-item-wrapper divider"
[ngClass]="
!!item && !!item.classes && !!item.classes.wrapper
? item.classes.wrapper
: ''
"
></div>

View File

@ -0,0 +1,65 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-vertical-navigation-divider-item',
templateUrl: './divider.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseVerticalNavigationDividerItemComponent
implements OnInit, OnDestroy
{
@Input() item?: FuseNavigationItem;
@Input() name?: string;
private _fuseVerticalNavigationComponent?: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseVerticalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
}

View File

@ -0,0 +1,111 @@
<!-- Item wrapper -->
<div
class="fuse-vertical-navigation-item-wrapper"
[class.fuse-vertical-navigation-item-has-subtitle]="!!item?.subtitle"
[ngClass]="
!!item && item.classes && item.classes.wrapper ? item.classes.wrapper : ''
"
>
<div class="fuse-vertical-navigation-item">
<!-- Icon -->
<ng-container *ngIf="item?.icon">
<mat-icon
class="fuse-vertical-navigation-item-icon"
[ngClass]="
!!item && item.classes && item.classes.icon ? item.classes.icon : ''
"
[svgIcon]="!!item && !!item.icon ? item.icon : ''"
></mat-icon>
</ng-container>
<!-- Title & Subtitle -->
<div class="fuse-vertical-navigation-item-title-wrapper">
<div class="fuse-vertical-navigation-item-title">
<span
[ngClass]="
!!item && item.classes && item.classes.title
? item.classes.title
: ''
"
>
{{ item?.title }}
</span>
</div>
<ng-container *ngIf="item?.subtitle">
<div class="fuse-vertical-navigation-item-subtitle">
<span
[ngClass]="
!!item && !!item.classes && !!item.classes.subtitle
? item.classes.subtitle
: ''
"
>
{{ item?.subtitle }}
</span>
</div>
</ng-container>
</div>
<!-- Badge -->
<ng-container *ngIf="item?.badge">
<div class="fuse-vertical-navigation-item-badge">
<div
class="fuse-vertical-navigation-item-badge-content"
[ngClass]="
!!item && !!item.badge && !!item.badge.classes
? item.badge.classes
: ''
"
>
{{ item?.badge?.title }}
</div>
</div>
</ng-container>
</div>
</div>
<ng-container *ngFor="let item of item?.children; trackBy: trackByFn">
<!-- Skip the hidden items -->
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
<!-- Basic -->
<ng-container *ngIf="item.type === 'basic'">
<fuse-vertical-navigation-basic-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-basic-item>
</ng-container>
<!-- Collapsable -->
<ng-container *ngIf="item.type === 'collapsable'">
<fuse-vertical-navigation-collapsable-item
[item]="item"
[name]="name"
[autoCollapse]="autoCollapse"
></fuse-vertical-navigation-collapsable-item>
</ng-container>
<!-- Divider -->
<ng-container *ngIf="item.type === 'divider'">
<fuse-vertical-navigation-divider-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-divider-item>
</ng-container>
<!-- Group -->
<ng-container *ngIf="item.type === 'group'">
<fuse-vertical-navigation-group-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-group-item>
</ng-container>
<!-- Spacer -->
<ng-container *ngIf="item.type === 'spacer'">
<fuse-vertical-navigation-spacer-item
[item]="item"
[name]="name"
></fuse-vertical-navigation-spacer-item>
</ng-container>
</ng-container>
</ng-container>

View File

@ -0,0 +1,85 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnDestroy,
OnInit,
} from '@angular/core';
import { BooleanInput } from '@angular/cdk/coercion';
import { Subject, takeUntil } from 'rxjs';
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
@Component({
selector: 'fuse-vertical-navigation-group-item',
templateUrl: './group.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FuseVerticalNavigationGroupItemComponent
implements OnInit, OnDestroy
{
/* eslint-disable @typescript-eslint/naming-convention */
static ngAcceptInputType_autoCollapse: BooleanInput;
/* eslint-enable @typescript-eslint/naming-convention */
@Input() autoCollapse: boolean = false;
@Input() item?: FuseNavigationItem;
@Input() name?: string;
private _fuseVerticalNavigationComponent?: FuseVerticalNavigationComponent;
private _unsubscribeAll: Subject<any> = new Subject<any>();
/**
* Constructor
*/
constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _fuseNavigationService: FuseNavigationService
) {}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On init
*/
ngOnInit(): void {
// Get the parent navigation component
this._fuseVerticalNavigationComponent =
this._fuseNavigationService.getComponent(this.name);
// Subscribe to onRefreshed on the navigation component
this._fuseVerticalNavigationComponent?.onRefreshed
.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
// Mark for check
this._changeDetectorRef.markForCheck();
});
}
/**
* On destroy
*/
ngOnDestroy(): void {
// Unsubscribe from all subscriptions
this._unsubscribeAll.next(null);
this._unsubscribeAll.complete();
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Track by function for ngFor loops
*
* @param index
* @param item
*/
trackByFn(index: number, item: any): any {
return item.id || index;
}
}

Some files were not shown because too many files have changed in this diff Show More