1 import { io } from 'socket.io-client';
2 import { authToken } from './http';
3 import { TimeManager } from '../shared/time';
4 import { configureChat } from './chat';
6 function $<T>(selector: string, root: any = document): T {
7 return root.querySelector(selector) as T;
10 function $$<T>(selector: string, root: any = document): T[] {
11 return Array.from(root.querySelectorAll(selector)) as T[];
13 function setTimeGradient() {
14 const gradientName = time.gradientName();
15 const $body = $<HTMLElement>('body');
16 $body.classList.value = gradientName;
18 $body.classList.add(time.getTimePeriod());
21 if(time.get24Hour() >= 5 && time.get24Hour() < 9) {
24 else if(time.get24Hour() >= 9 && time.get24Hour() < 17) {
27 else if(time.get24Hour() >= 17 && time.get24Hour() < 20) {
34 $<HTMLElement>('#time-of-day').innerHTML = `<img src="/assets/img/icons/time-of-day/${icon}.png"> ${time.getHour()}${time.getAmPm()}`;
38 const time = new TimeManager();
41 'x-authtoken': authToken()
45 setInterval(setTimeGradient, 60 * 1000);
47 socket.on('connect', () => {
48 console.log(`Connected: ${socket.id}`);
51 socket.on('authToken', (authToken: string) => {
52 console.log(`recv auth token ${authToken}`);
53 localStorage.setItem('authToken', authToken);
57 socket.on('ready', bootstrap);
60 $$<HTMLElement>('nav a').forEach(el => {
61 el.addEventListener('click', e => {
62 const el = e.target as HTMLElement;
64 $$<HTMLElement>('a', el.closest('nav')).forEach(el => {
65 el.classList.remove('active');
68 el.classList.add('active');
70 const targetEl = $<HTMLElement>(el.getAttribute('hx-target')!.toString());
72 Array.from(targetEl.parentElement!.children).forEach(el => {
73 el.classList.remove('active');
75 targetEl.classList.add('active');
79 $<HTMLElement>('body').addEventListener('click', e => {
80 const target = e.target as HTMLElement;
82 if(target!.parentElement!.classList.contains('filter')) {
83 // ok this is afunky filter object!
84 const children = Array.from(target!.parentElement!.children);
85 children.forEach(el => el.classList.remove('active'));
86 target.classList.add('active');
88 const dataFilter = target.getAttribute('data-filter');
90 const targetPane = $<HTMLElement>(`.filter-result[data-filter="${dataFilter}"]`, target.closest('.filter-container'));
93 Array.from(targetPane!.parentElement!.children).forEach(el => {
94 if(el.getAttribute('data-filter') === dataFilter) {
95 el.classList.remove('hidden');
96 el.classList.add('active');
99 el.classList.add('hidden');
100 el.classList.remove('active');
106 if(target.getAttribute('formmethod') === 'dialog' && target.getAttribute('value') === 'cancel') {
107 target.closest('dialog')?.close();
111 const modalMutations = new MutationObserver((list, observer) => {
117 list.forEach(mutation => {
118 switch(((mutation.target) as HTMLElement).id) {
119 case 'modal-wrapper':
130 if($<HTMLElement>('#modal-wrapper').children.length) {
131 $$<HTMLDialogElement>('#modal-wrapper dialog').forEach(el => {
140 if($<HTMLElement>('#alerts').children.length) {
141 $$<HTMLElement>('#alerts .alert').forEach(el => {
142 if(!el.getAttribute('data-dismiss-at')) {
143 const dismiss = Date.now() + 3000;
144 el.setAttribute('data-dismiss-at', dismiss.toString());
145 setTimeout(() => { el.remove(); }, 3000);
153 modalMutations.observe($<HTMLElement>('#modal-wrapper'), { childList: true });
155 modalMutations.observe($<HTMLElement>('#alerts'), { childList: true });
158 function bootstrap() {
159 console.log('Server connection verified');
160 configureChat(socket);
161 $$<HTMLElement>('nav a')[0].click();
163 document.body.addEventListener('htmx:configRequest', function(evt) {
165 evt.detail.headers['x-authtoken'] = authToken();
167 document.body.addEventListener('htmx:load', function(evt) {
168 $$<HTMLElement>('.disabled[data-block]').forEach(el => {
169 setTimeout(() => { el.removeAttribute('disabled'); }, 3000);
172 document.body.addEventListener('htmx:beforeSwap', function(e) {
173 const el = e.target as HTMLElement;
174 if(el.id === 'chat-form') {
175 $<HTMLInputElement>('#message').value = '';