diff --git a/chatto/src/main/javascript/package.json b/chatto/src/main/javascript/package.json index e79825e..6a8c22b 100644 --- a/chatto/src/main/javascript/package.json +++ b/chatto/src/main/javascript/package.json @@ -35,7 +35,7 @@ "dompurify": "global:DOMPurify", "fuse.js": "global:Fuse", "sjcl": "global:sjcl", - "sprintf-js": "global:sprintf2", + "sprintf-js": "global:sprintf", "alertifyjs": "global:alertify" } } \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/src/SprintfTest.d.ts b/chatto/src/main/javascript/ts/src/SprintfTest.d.ts new file mode 100644 index 0000000..650aede --- /dev/null +++ b/chatto/src/main/javascript/ts/src/SprintfTest.d.ts @@ -0,0 +1,9 @@ +import { sprintf } from "sprintf-js"; + +// export as namespace sprintf; +// export = sprintf; + +declare global { + // const Hls: typeof Hls; + var Sprintf: typeof sprintf; +} \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/src/main.ts b/chatto/src/main/javascript/ts/src/main.ts index 76aaac6..daeaafe 100644 --- a/chatto/src/main/javascript/ts/src/main.ts +++ b/chatto/src/main/javascript/ts/src/main.ts @@ -21,12 +21,20 @@ import { FuseSearchService } from "./service/FuseSearchService"; import { ChatMessageDTO } from "./dto/ChatMessageDTO"; import { NotificationService } from "./service/NotificationService"; import { AlertifyNotificationService } from "./service/AlertifyNotificationService"; -import * as sprintf2 from "sprintf-js"; +/// +// import "./SprintfTest.d.ts" +// import { sprintf } from "sprintf-js"; +// import sprintf = require('sprintf-js'); +import { TemplateFactory } from "./template/TemplateFactory"; +import { UserViewDeps } from "./view/UserViewDeps"; +import { ChatViewDeps } from "./view/ChatViewDeps"; +import { MarkDownItMarkDownService } from "./service/MarkDownItMarkDownService"; const usersListElement = document.getElementById('contacts-box'); const userSearchButton = document.getElementById('user-search'); -const userSearchInputElement = document.getElementById('user-search-term') -const userSearchCancelButton = document.getElementById('user-search-cancel') +const userSearchInputElement = document.getElementById('user-search-term') as HTMLInputElement; +const userSearchCancelButton = document.getElementById('user-search-cancel'); +const searchService: SearchService = new FuseSearchService(["userName"]); log.setLevel("TRACE") @@ -34,8 +42,22 @@ const chatModel = new ChatModel(); const userModel = new UserModel(); // const userModel = ModelFactory.createModel("USER"); -// @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. -const userView = new UserView(userModel, chatModel, usersListElement, userSearchInputElement, userSearchButton, userSearchCancelButton); + +const uvDeps: UserViewDeps = { + model: userModel, + chatModel: chatModel, + // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. + usersListElement: usersListElement, + userSearchInputElement: userSearchInputElement, + // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. + userSearchButton: userSearchButton, + // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. + userSearchCancelButton: userSearchCancelButton, + searchService: searchService, + userContactOnlineTemplate: TemplateFactory.getTemplate('user-contact-online-template'), + userContactOfflineTemplate: TemplateFactory.getTemplate('user-contact-offline-template') +} +const userView = new UserView(uvDeps); // console.log(userBox); @@ -53,7 +75,17 @@ log.info("hello"); const chatArea = document.getElementById('chat-area-new'); // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. -const chatView = new ChatView(chatModel, chatArea); +const cvDeps: ChatViewDeps = { + chatModel: chatModel, + // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'. + messageContainer: chatArea, + messageSendTemplate: TemplateFactory.getTemplate('msg_container_send_template'), + messageReceiveTemplate: TemplateFactory.getTemplate('msg_container_template'), + markdownService: new MarkDownItMarkDownService, + encryptionService: new SJCLEncryptionService + +} +const chatView = new ChatView(cvDeps); chatModel.attach(chatView); const chatController = new ChatController(chatModel, chatView); @@ -76,18 +108,20 @@ var msgContainerTemplate = Handlebars.compile(source); JsonAPI.ACTIVE_USERS_GET + 'aef'; const encryptionService: EncryptionService = new SJCLEncryptionService(); -let messageCipherDTO: MessageCipherDTO = encryptionService.encrypt("password","data"); +let messageCipherDTO: MessageCipherDTO = encryptionService.encrypt("password", "data"); console.log(encryptionService.decrypt("password", messageCipherDTO)); -Handlebars.registerHelper('avatar', function() { +Handlebars.registerHelper('avatar', function () { return '
'; }); const testList: ChatMessageDTO[] = []; -const cmSearchService: SearchService = new FuseSearchService(["userName"]); + +// @ts-ignore +console.log() // @ts-ignore -log.info(sprintf("test sprintf")) -log.info(sprintf2.sprintf("test sprintf")) +log.info(Sprintf("test sprintf")) +// log.info(sprintf2.sprintf("test sprintf")) const ns: NotificationService = new AlertifyNotificationService(); ns.success("Welcome"); // ns.errorWithDelay("Hmm very long error notif", 10); \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/src/model/FetchErrorHandler.ts b/chatto/src/main/javascript/ts/src/model/FetchErrorHandler.ts index 64f9cfb..890d544 100644 --- a/chatto/src/main/javascript/ts/src/model/FetchErrorHandler.ts +++ b/chatto/src/main/javascript/ts/src/model/FetchErrorHandler.ts @@ -1,5 +1,7 @@ import log = require("loglevel"); -import { sprintf } from "sprintf-js"; +// import { sprintf } from "sprintf-js"; +/// + // import sprintf = require('sprintf-js').sprintf; export function fetchErrorHandler(response: Response) { @@ -10,6 +12,7 @@ export function fetchErrorHandler(response: Response) { // throw new Error(response.statusText); // window.alert(sprintf('Some error occured. Http code is %s', response.status)); // alertify.error(sprintf('Some error occured. Http code is %s', response.status)); + // @ts-ignore log.error(sprintf('Some error occured. Http code is %s', response.status)); log.error(); return true; @@ -18,6 +21,7 @@ export function fetchErrorHandler(response: Response) { // throw new Error(json.error.message); // example error message returned by a REST API // window.alert(sprintf('Error: %s (Http code %s)', json, response.status)); // alertify.error(sprintf('Some error occured. Http code is %s', response.status)); + // @ts-ignore log.error(sprintf('Some error occured. Http code is %s', response.status)); log.error(json); return true; diff --git a/chatto/src/main/javascript/ts/src/view/ChatView.ts b/chatto/src/main/javascript/ts/src/view/ChatView.ts index 24b0bce..c5f1e69 100644 --- a/chatto/src/main/javascript/ts/src/view/ChatView.ts +++ b/chatto/src/main/javascript/ts/src/view/ChatView.ts @@ -12,23 +12,32 @@ import { SJCLEncryptionService } from "../service/SJCLEncryptionService"; import { EncryptionService } from "../service/EncryptionService"; import { ChatMessageDTO } from "../dto/ChatMessageDTO"; import { fetchHandler } from "./FetchHandler"; +import { ChatViewDeps } from "./ChatViewDeps"; export class ChatView implements Observer { private readonly _chatModel: ChatModel; private readonly _messageContainer: HTMLElement; - private readonly _messageSendTemplate = TemplateFactory.getTemplate('msg_container_send_template'); - private readonly _messageReceiveTemplate = TemplateFactory.getTemplate('msg_container_template'); - private readonly _markdownService: MarkDownService = new MarkDownItMarkDownService(); - private readonly _encryptionService: EncryptionService = new SJCLEncryptionService(); - - - constructor(chatModel: ChatModel, messageContainer: HTMLElement) { - this._messageContainer = messageContainer; - this._chatModel = chatModel; + // private readonly _messageSendTemplate = TemplateFactory.getTemplate('msg_container_send_template'); + // private readonly _messageReceiveTemplate = TemplateFactory.getTemplate('msg_container_template'); + // private readonly _markdownService: MarkDownService = new MarkDownItMarkDownService(); + // private readonly _encryptionService: EncryptionService = new SJCLEncryptionService(); + + private readonly _messageSendTemplate: Handlebars.TemplateDelegate; + private readonly _messageReceiveTemplate: Handlebars.TemplateDelegate; + private readonly _markdownService: MarkDownService; + private readonly _encryptionService: EncryptionService; + + + constructor(deps: ChatViewDeps) { + this._messageContainer = deps.messageContainer; + this._chatModel = deps.chatModel; + this._messageSendTemplate = deps.messageSendTemplate; + this._messageReceiveTemplate = deps.messageReceiveTemplate; + this._markdownService = deps.markdownService; + this._encryptionService = deps.encryptionService; this.addEventListeners(); } - update(data: ChatMessageViewModel[]): void { log.info('ChatView: updating view'); // let html: string = ""; @@ -108,7 +117,8 @@ export class ChatView implements Observer { // @ts-ignore const messageContent = chatInput.value; - const context = { fromUser: JsonAPI.principleName, message: this._markdownService.render(messageContent), messageTime: new Date().toLocaleString() }; + const context = { fromUser: JsonAPI.principleName, toUser: "", message: this._markdownService.render(messageContent), messageTime: new Date().toLocaleString() }; + // @ts-ignore const msgContainer: string = this._messageSendTemplate(context); $(this._messageContainer).append(DOMPurify.sanitize(msgContainer)); // scrollChatAreaAnimated(2400); diff --git a/chatto/src/main/javascript/ts/src/view/ChatViewDeps.ts b/chatto/src/main/javascript/ts/src/view/ChatViewDeps.ts new file mode 100644 index 0000000..1f55720 --- /dev/null +++ b/chatto/src/main/javascript/ts/src/view/ChatViewDeps.ts @@ -0,0 +1,14 @@ +import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel"; +import { ChatModel } from "../model/ChatModel"; +import { MarkDownService } from "../service/MarkDownService"; +import { EncryptionService } from "../service/EncryptionService"; + +export interface ChatViewDeps { + chatModel: ChatModel; + messageContainer: HTMLElement; + messageSendTemplate: Handlebars.TemplateDelegate; + messageReceiveTemplate: Handlebars.TemplateDelegate; + markdownService: MarkDownService; + encryptionService: EncryptionService; + +} \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/src/view/UserView.ts b/chatto/src/main/javascript/ts/src/view/UserView.ts index 15dec8e..eac4408 100644 --- a/chatto/src/main/javascript/ts/src/view/UserView.ts +++ b/chatto/src/main/javascript/ts/src/view/UserView.ts @@ -1,18 +1,15 @@ import { Observer } from "../observe/Observer"; -import { Model } from "../model/AbstractModel"; -import { Subject } from "../observe/Observable"; -import { View } from "./AbstractView"; -import { Controller } from "../controller/AbstractController"; -import { TemplateFactory } from "../template/TemplateFactory"; import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel"; import { ChatModel } from "../model/ChatModel"; import log = require("loglevel"); import * as DOMPurify from "dompurify"; import { SearchService } from "../service/SearchService"; -import { FuseSearchService } from "../service/FuseSearchService"; import { UserModel } from "../model/UserModel"; +import { UserViewDeps } from "./UserViewDeps"; export class UserView implements Observer { + + private readonly _model: UserModel; private readonly _chatModel: ChatModel; private readonly _usersListElement: HTMLElement; @@ -20,18 +17,19 @@ export class UserView implements Observer { private readonly _userSearchButton: HTMLElement; private readonly _userSearchCancelButton: HTMLElement; private readonly _searchService: SearchService; - private readonly _userContactOnlineTemplate: Handlebars.TemplateDelegate = TemplateFactory.getTemplate('user-contact-online-template'); - private readonly _userContactOfflineTemplate: Handlebars.TemplateDelegate = TemplateFactory.getTemplate('user-contact-offline-template'); - - constructor(model: UserModel, chatModel: ChatModel, usersListElement: HTMLElement, - userSearchInputElement: HTMLInputElement, userSearchButton: HTMLElement, userSearchCancelButton: HTMLElement) { - this._model = model; - this._chatModel = chatModel; - this._usersListElement = usersListElement; - this._userSearchInputElement = userSearchInputElement; - this._userSearchButton = userSearchButton - this._searchService = new FuseSearchService(["userName"]); - this._userSearchCancelButton = userSearchCancelButton; + private readonly _userContactOnlineTemplate: Handlebars.TemplateDelegate; + private readonly _userContactOfflineTemplate: Handlebars.TemplateDelegate; + + constructor(deps: UserViewDeps) { + this._model = deps.model; + this._chatModel = deps.chatModel; + this._usersListElement = deps.usersListElement; + this._userSearchInputElement = deps.userSearchInputElement; + this._userSearchButton = deps.userSearchButton; + this._userSearchCancelButton = deps.userSearchCancelButton; + this._searchService = deps.searchService; + this._userContactOnlineTemplate = deps.userContactOnlineTemplate; + this._userContactOfflineTemplate = deps.userContactOfflineTemplate; this.addSearchEventListeners(); } @@ -39,7 +37,7 @@ export class UserView implements Observer { update(data: ActiveUserViewModel[]): void { let html: string = ""; data.forEach((element: ActiveUserViewModel) => { - element.online ? html+=this._userContactOnlineTemplate(element) : html+=this._userContactOfflineTemplate(element); + element.online ? html += this._userContactOnlineTemplate(element) : html += this._userContactOfflineTemplate(element); }); $(this._usersListElement).html(DOMPurify.sanitize(html)); this.addUserCallBacks(); diff --git a/chatto/src/main/javascript/ts/src/view/UserViewDeps.ts b/chatto/src/main/javascript/ts/src/view/UserViewDeps.ts new file mode 100644 index 0000000..6b29880 --- /dev/null +++ b/chatto/src/main/javascript/ts/src/view/UserViewDeps.ts @@ -0,0 +1,19 @@ +import { UserModel } from "../model/UserModel"; + +import { ChatModel } from "../model/ChatModel"; + +import { SearchService } from "../service/SearchService"; + +import { ActiveUserViewModel } from "../viewmodel/ActiveUserViewModel"; + +export interface UserViewDeps { + model: UserModel; + chatModel: ChatModel; + usersListElement: HTMLElement; + userSearchInputElement: HTMLInputElement; + userSearchButton: HTMLElement; + userSearchCancelButton: HTMLElement; + searchService: SearchService; + userContactOnlineTemplate: Handlebars.TemplateDelegate; + userContactOfflineTemplate: Handlebars.TemplateDelegate; +} \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/tsconfig.json b/chatto/src/main/javascript/ts/tsconfig.json index c68c712..53ad2ef 100644 --- a/chatto/src/main/javascript/ts/tsconfig.json +++ b/chatto/src/main/javascript/ts/tsconfig.json @@ -46,7 +46,7 @@ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */