From 3c4db7d05e6ae2e24529bdbf8f49992cd703442f Mon Sep 17 00:00:00 2001 From: dtookey-at-783322121474 Date: Thu, 10 Dec 2020 15:58:05 -0500 Subject: [PATCH 1/3] began implementation of map merge between web and file cards. --- gulpfile.js | 10 +++- package-lock.json | 6 +-- package.json | 1 + src/ts_source/fileutils.ts | 93 +++++++++++++++++++++++++++++++++++++- src/ts_source/themes.ts | 2 +- tests/fileutils-test.ts | 20 ++++++-- 6 files changed, 122 insertions(+), 10 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 27d02a0..679125c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -64,6 +64,11 @@ function scss() { .pipe(dest('build/assets/pages/styles/')); } +function tests() { + return src('tests/*',) + .pipe(dest('build/tests/')); +} + function root() { return src('src/*.js') .pipe(dest('build/')); @@ -115,4 +120,7 @@ exports.clean = clean; exports.default = series(validateConfigSources, conf, style, scss, root, pkg, typescript, dependencies); -exports.runFast = series(validateConfigSources, conf, style, scss, root, pkg) \ No newline at end of file +exports.tests = series(validateConfigSources, conf, style, scss, root, pkg, typescript, dependencies, tests); + +exports.runFast = series(validateConfigSources, conf, style, scss, root, pkg) + diff --git a/package-lock.json b/package-lock.json index a72d8ad..68fb319 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3540,9 +3540,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", "dev": true }, "interpret": { diff --git a/package.json b/package.json index 5324dba..8e6f233 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "gulp-typescript": "^6.0.0-alpha.1", "gulp-exec": "^5.0.0", "del": "^6.0.0", + "mocha": "^8.2.1", "electron-mocha": "^9.3.1", "chai": "^4.2.0", "nyc": "^15.1.0", diff --git a/src/ts_source/fileutils.ts b/src/ts_source/fileutils.ts index c730e23..1c00146 100644 --- a/src/ts_source/fileutils.ts +++ b/src/ts_source/fileutils.ts @@ -2,7 +2,6 @@ let path = require('path') let fs = require('fs'); const shell = require('electron').shell; let fileExtensionToImage: object; -import {Themes} from "./themes"; export enum ConfigPaths { ApplicationConfigName = "dashboard.json", @@ -49,7 +48,7 @@ export module Configurator { function buildDefaultConfig(): object { let userConfig = {}; - userConfig['theme'] = Themes.AppTheme.Dark; + userConfig['theme'] = "theme-dark"; saveUserConfig(ConfigPaths.UserConfigName, userConfig) return userConfig } @@ -106,6 +105,57 @@ export class DocumentDirectory { root: DirectoryNode; + getCards(): object { + return DocumentDirectory.walkCards(this.root); + + } + + private static walkCards(d: DirectoryNode): Map { + let cardsByCategory = new Map(); + for (let i = 0, l = d.children.length; i < l; i++) { + let child = d.children[i]; + if (child instanceof DirectoryNode) { + let dir = child as DirectoryNode; + if (dir.containsDirectory()) { + let childDirectories = dir.getDirectories(); + for (let j = 0, k = childDirectories.length; j < k; j++) { + let dir = childDirectories[j]; + let subCards = DocumentDirectory.walkCards(dir); + this.mergeMaps(cardsByCategory, subCards); + } + } + let sCards = dir.getDocuments() + } else { + let category = (child.parent as DirectoryNode).getCategory(); + let cards = cardsByCategory.get(category); + if (cards === undefined || cards === null) { + cards = []; + } + cards.push(child.toCard()); + cardsByCategory.set(category, cards); + } + } + + return cardsByCategory; + } + + private static mergeMaps(a: Map, b: Map) { + let keys = Object.keys(b); + for (let z in keys) { + let key = keys[z]; + let sa = a.get(key) + if (sa === undefined || sa === null) { + sa = []; + } + let sb = b.get(key) + if (sb === undefined || sa === null) { + sb = []; + } + sa.push(...sb); + a[key] = sa; + } + } + } export class FileNode { @@ -122,6 +172,26 @@ export class FileNode { shell.openItem(this.filePath); } + toCard(): object { + let cardObj = { + "title": this.getTitle(), + "description": "", + "imagePath": "", + "urlText": this.filePath, + "altText": "" + } + return cardObj + } + + getTitle(): String { + let name = path.basename(this.filePath); + return name + } + + isDescriptor() { + + } + static compare(a: FileNode, b: FileNode): number { return a.filePath.localeCompare(b.filePath); } @@ -164,6 +234,25 @@ export class DirectoryNode extends FileNode { return x instanceof DirectoryNode }) as DirectoryNode[] } + + containsDirectory(): Boolean { + for (let i = 0, l = this.children.length; i < l; i++) { + let child = this.children[i]; + if (child instanceof DirectoryNode) return true; + } + return false + } + + getCategory(): String { + let rawName = path.basename(this.filePath); + let parts = rawName.split("-"); + for (let i = 0, l = parts.length; i < l; i++) { + let part = parts[i].split(''); + part[0] = part[0].toUpperCase(); + parts[i] = part.join('') + } + return parts.join(" ") + } } diff --git a/src/ts_source/themes.ts b/src/ts_source/themes.ts index a931774..2f8b9ec 100644 --- a/src/ts_source/themes.ts +++ b/src/ts_source/themes.ts @@ -73,4 +73,4 @@ export module Themes { } } -Themes.initTheme(); +Themes.initTheme(); \ No newline at end of file diff --git a/tests/fileutils-test.ts b/tests/fileutils-test.ts index 0513e92..f98ba57 100644 --- a/tests/fileutils-test.ts +++ b/tests/fileutils-test.ts @@ -7,6 +7,7 @@ describe('fileutils', () => { it('DocumentDirectory Constructor fail-on-not-exist', testDocumentDirectoryFailNoExist) it('DocumentDirectory Constructor fail-on-file', testDocumentDirectoryFailFile) it('documentDirectoryConstructor - debug', testDocumentDirectoryConstructor); + it('pass by test', passBy); }); function testDocumentDirectoryFailNoExist() { @@ -24,9 +25,22 @@ function testDocumentDirectoryFailFile() { } function testDocumentDirectoryConstructor() { - let directoryPath = path.join(__dirname, "../src/assets/documents"); + let directoryPath = path.join(__dirname, "../src/assets/resources"); let documents = new DocumentDirectory(directoryPath); - console.log(documents); - console.log((documents.root.getDirectories()[0].children)); + documents.getCards() } + +function passBy(){ + let a = ["a", "b"]; + let b = ["c", "d"]; + testCopy(a, b); + for(let c in a){ + console.log(c); + } +} + + +function testCopy(a: String[], b: String[]){ + a.push(...b); +} From 844a26e2a1354960f0c0f6df500bc1bedab8273d Mon Sep 17 00:00:00 2001 From: dtookey Date: Wed, 16 Dec 2020 11:59:48 -0500 Subject: [PATCH 2/3] file-specific configs implemented --- src/assets/resources/coming-soon.pdf.json | 5 +++ src/ts_source/fileutils.ts | 47 ++++++++++++++++++++--- tests/fileutils-test.ts | 22 +++-------- 3 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 src/assets/resources/coming-soon.pdf.json diff --git a/src/assets/resources/coming-soon.pdf.json b/src/assets/resources/coming-soon.pdf.json new file mode 100644 index 0000000..6a3ae3e --- /dev/null +++ b/src/assets/resources/coming-soon.pdf.json @@ -0,0 +1,5 @@ +{ + "description": "Coming soon pdf", + "imagePath": "../resources/coming-soon.pdf", + "show": true +} \ No newline at end of file diff --git a/src/ts_source/fileutils.ts b/src/ts_source/fileutils.ts index 1c00146..6a1c547 100644 --- a/src/ts_source/fileutils.ts +++ b/src/ts_source/fileutils.ts @@ -1,3 +1,5 @@ + + let path = require('path') let fs = require('fs'); const shell = require('electron').shell; @@ -107,7 +109,6 @@ export class DocumentDirectory { getCards(): object { return DocumentDirectory.walkCards(this.root); - } private static walkCards(d: DirectoryNode): Map { @@ -124,7 +125,17 @@ export class DocumentDirectory { this.mergeMaps(cardsByCategory, subCards); } } - let sCards = dir.getDocuments() + let sCards = dir.getDocuments(); + let category = dir.getCategory(); + for (let sCard in sCards) { + let scrd = sCards[sCard]; + let cards = cardsByCategory.get(category); + if (cards === undefined || cards === null) { + cards = []; + } + cards.push(scrd.toCard()); + cardsByCategory.set(category, cards); + } } else { let category = (child.parent as DirectoryNode).getCategory(); let cards = cardsByCategory.get(category); @@ -148,7 +159,7 @@ export class DocumentDirectory { sa = []; } let sb = b.get(key) - if (sb === undefined || sa === null) { + if (sb === undefined) { sb = []; } sa.push(...sb); @@ -168,24 +179,50 @@ export class FileNode { this.parent = parent; } + static loadAltProps(path: String): object { + let props = {}; + let jsonPath = path + ".json" + if (fs.existsSync(jsonPath)) { + let raw = fs.readFileSync(jsonPath); + props = JSON.parse(raw.toString()); + } + return props + } + open() { shell.openItem(this.filePath); } + show() { + shell.showItemInFolder(this.filePath); + } + toCard(): object { + let altProps = FileNode.loadAltProps(this.filePath) let cardObj = { "title": this.getTitle(), "description": "", "imagePath": "", "urlText": this.filePath, - "altText": "" + "altText": "", + "fileCard": true } + + let altKeys = Object.keys(altProps); + for (let kidx in altKeys) { + let key = altKeys[kidx]; + cardObj[key] = altProps[key] + } + return cardObj } getTitle(): String { let name = path.basename(this.filePath); - return name + let ext = path.extname(name); + let cName = name.replace(ext, ""); + cName = cName.replace(/[\-._]/ig, " ") + return `${cName} (${ext.substr(1).toUpperCase()})` } isDescriptor() { diff --git a/tests/fileutils-test.ts b/tests/fileutils-test.ts index f98ba57..d69f074 100644 --- a/tests/fileutils-test.ts +++ b/tests/fileutils-test.ts @@ -2,12 +2,13 @@ import {DocumentDirectory, FileNode} from "../src/ts_source/fileutils"; const path = require('path'); const chai = require('chai'); +const {performance} = require('perf_hooks'); describe('fileutils', () => { it('DocumentDirectory Constructor fail-on-not-exist', testDocumentDirectoryFailNoExist) it('DocumentDirectory Constructor fail-on-file', testDocumentDirectoryFailFile) it('documentDirectoryConstructor - debug', testDocumentDirectoryConstructor); - it('pass by test', passBy); + }); function testDocumentDirectoryFailNoExist() { @@ -26,21 +27,10 @@ function testDocumentDirectoryFailFile() { function testDocumentDirectoryConstructor() { let directoryPath = path.join(__dirname, "../src/assets/resources"); + let start = performance.now() let documents = new DocumentDirectory(directoryPath); - documents.getCards() - -} - -function passBy(){ - let a = ["a", "b"]; - let b = ["c", "d"]; - testCopy(a, b); - for(let c in a){ - console.log(c); - } -} - + let end = performance.now() + console.log(documents.getCards()); + console.log(`Execution time: ${end-start}ms`) -function testCopy(a: String[], b: String[]){ - a.push(...b); } From 7200099f127e8558a7a0de6dfd714f9e8ad82b2e Mon Sep 17 00:00:00 2001 From: dtookey Date: Wed, 16 Dec 2020 12:34:31 -0500 Subject: [PATCH 3/3] first path of file factory is finished --- src/assets/conf/file-extensions.json | 5 +- src/assets/conf/resources-landing-page.json | 19 ++---- src/assets/resources/coming-soon.pdf.json | 1 - .../marketing/JDS_faulkner_Logo.eps.json | 5 ++ src/ts_source/fileutils.ts | 16 +++-- src/ts_source/viewFactory.ts | 68 ++++++++++++------- 6 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 src/assets/resources/marketing/JDS_faulkner_Logo.eps.json diff --git a/src/assets/conf/file-extensions.json b/src/assets/conf/file-extensions.json index 4e7a0a2..819b309 100644 --- a/src/assets/conf/file-extensions.json +++ b/src/assets/conf/file-extensions.json @@ -1,3 +1,6 @@ { - ".pdf": "pdf-icon.svg" + ".pdf": "pdf-icon-100x100.png", + ".eps": "image-eps-icon.png", + ".png": "image-png-icon.png", + ".docx": "word-icon-100x100.png" } \ No newline at end of file diff --git a/src/assets/conf/resources-landing-page.json b/src/assets/conf/resources-landing-page.json index a65a801..73630a9 100644 --- a/src/assets/conf/resources-landing-page.json +++ b/src/assets/conf/resources-landing-page.json @@ -1,8 +1,9 @@ { "grid-container": { - - - + "Resources": { + "description": "Top level resources", + "cards": [] + }, "Human Resources": { "description": "Policies, recruitment, onboarding, benefits and compensation", "cards": [ @@ -71,8 +72,6 @@ } ] }, - - "Marketing": { "description": "Client-facing media, publications, public relations and advertising", "cards": [ @@ -141,8 +140,6 @@ } ] }, - - "Productivity": { "description": "Basic work tools, e-mail, calendar, document applications and cloud storage", "cards": [ @@ -176,8 +173,6 @@ } ] }, - - "Training": { "description": "Career growth, skills development, online courses, manuals and references", "cards": [ @@ -220,13 +215,11 @@ "title": "Deltek University", "description": "Increase your Deltek knowledge with courses designed to teach you how to use Deltek solutions.", "imagePath": "deltek-logo-black.png", - "urlText":"https://www.deltek.com/en/support/deltek-university", - "altText": "Deltek logo" + "urlText": "https://www.deltek.com/en/support/deltek-university", + "altText": "Deltek logo" } ] }, - - "Workflow": { "description": "Project management, task assignment and status, client information, invoicing and reports", "cards": [ diff --git a/src/assets/resources/coming-soon.pdf.json b/src/assets/resources/coming-soon.pdf.json index 6a3ae3e..48aa54d 100644 --- a/src/assets/resources/coming-soon.pdf.json +++ b/src/assets/resources/coming-soon.pdf.json @@ -1,5 +1,4 @@ { "description": "Coming soon pdf", - "imagePath": "../resources/coming-soon.pdf", "show": true } \ No newline at end of file diff --git a/src/assets/resources/marketing/JDS_faulkner_Logo.eps.json b/src/assets/resources/marketing/JDS_faulkner_Logo.eps.json new file mode 100644 index 0000000..763657c --- /dev/null +++ b/src/assets/resources/marketing/JDS_faulkner_Logo.eps.json @@ -0,0 +1,5 @@ +{ + "title": "JDSfaulkner Logo - EPS", + "description": "Do you need to present the logo in your work? Here's an eps format to use in collateral and merchandise.", + "show": true +} \ No newline at end of file diff --git a/src/ts_source/fileutils.ts b/src/ts_source/fileutils.ts index 6a1c547..8a30a7b 100644 --- a/src/ts_source/fileutils.ts +++ b/src/ts_source/fileutils.ts @@ -1,5 +1,3 @@ - - let path = require('path') let fs = require('fs'); const shell = require('electron').shell; @@ -107,7 +105,7 @@ export class DocumentDirectory { root: DirectoryNode; - getCards(): object { + getCards(): Map { return DocumentDirectory.walkCards(this.root); } @@ -189,6 +187,12 @@ export class FileNode { return props } + private static getImagePathFromDocumentName(name: string): string { + let ext = FileUtils.getFileExtension(name); + let thumbnail = Configurator.getFileExtensionToImageMap()[ext]; + return thumbnail; + } + open() { shell.openItem(this.filePath); } @@ -198,11 +202,12 @@ export class FileNode { } toCard(): object { - let altProps = FileNode.loadAltProps(this.filePath) + let altProps = FileNode.loadAltProps(this.filePath); + let imageName = FileNode.getImagePathFromDocumentName(this.filePath); let cardObj = { "title": this.getTitle(), "description": "", - "imagePath": "", + "imagePath": imageName, "urlText": this.filePath, "altText": "", "fileCard": true @@ -244,6 +249,7 @@ export class DirectoryNode extends FileNode { if (stats.isDirectory()) { let contents = fs.readdirSync(filePath); for (let i = 0, l = contents.length; i < l; i++) { + if (path.extname(contents[i]) === ".json") continue; let childPath = path.join(filePath, contents[i]); let childStats = fs.lstatSync(childPath); if (childStats.isDirectory()) { diff --git a/src/ts_source/viewFactory.ts b/src/ts_source/viewFactory.ts index e0aa143..cb8cbdc 100644 --- a/src/ts_source/viewFactory.ts +++ b/src/ts_source/viewFactory.ts @@ -1,5 +1,6 @@ -import {Configurator, FileUtils} from './fileutils' +import {Configurator, DocumentDirectory, FileUtils} from './fileutils' import {loadTemplate, loadTemplateSingle} from "./templates" +import * as path from "path"; const shell = require('electron').shell; @@ -18,29 +19,43 @@ export class CardModel { } } -export function buildFileCard(filePath: string, elem: Element, append: boolean = false, $: any = require('jquery')) { - // let model = new CardModel(getImagePathFromDocumentName(filePath), fileNameToPrettyString(filePath)); - // loadTemplateSingle("file-card.mustache", model, (content: string, id: string) => { - // let snip = $(content); - // let container = $("#" + elem.id); - // - // if (append) { - // container.append(snip); - // } else { - // container.empty().append(snip); - // } - // setTimeout(() => { - // $(`#${id}`).on("click", () => { - // launchDocument(filePath); - // }); - // }, 1); //for some reason we have to let the dom breathe before it will let us do this? - // }); +export function buildFileCard(elem: JQuery, obj, append: boolean = false, $: any = require('jquery')) { + console.log(obj); + let model = new CardModel( + obj["title"], + obj["description"], + FileUtils.getPathToImage(obj["imagePath"]), + obj["urlText"] + ); + model["show"] = obj["show"]; + + loadTemplateSingle("web-card.mustache", model, (content: string, id: string) => { + if (append) { + elem.append(content); + } else { + elem.html(content) + } + + if (model["show"] !== undefined) { + $(`#${id}`).on("click", () => { + console.log("showing") + shell.showItemInFolder(model.resourcePath) + }); + } else { + $(`#${id}`).on("click", () => { + console.log("opening") + shell.openItem(model.resourcePath) + }); + } + }); } export function buildWebCardsFromConfig(configName: string) { let elementConfig = Configurator.loadAppConfig(configName); let $ = require('jquery') let containers = Object.keys(elementConfig); + let directoryPath = path.join(__dirname, "../assets/resources"); + let fileCards = new DocumentDirectory(directoryPath).getCards(); for (let i = 0, l = containers.length; i < l; i++) { let containerName = containers[i]; @@ -48,11 +63,15 @@ export function buildWebCardsFromConfig(configName: string) { let containerElem = $(`#${containerName}`); let containerCategories = Object.keys(containerObject); + containerCategories.push("Resources"); for (let j = 0, m = containerCategories.length; j < m; j++) { let categoryMetaObjectKey = containerCategories[j]; let categoryMetaObject = containerObject[categoryMetaObjectKey]; + let contentList = categoryMetaObject["cards"];//should be array of objects to render + let files = fileCards.get(categoryMetaObjectKey); + let categoryDescription = categoryMetaObject["description"]; let categoryKey = categoryMetaObjectKey.replace(/[\s,]/ig, '-').toLowerCase(); let categoryObject = { @@ -84,10 +103,17 @@ export function buildWebCardsFromConfig(configName: string) { } }); + for (let j in files) { + let file = files[j]; + buildFileCard(view, file, true, $) + } + for (let j = 0, m = contentList.length; j < m; j++) { let content = contentList[j]; buildWebCard(view, content, true, $); } + + } } @@ -128,12 +154,6 @@ function fileNameToPrettyString(fileName: string): string { return buffer.join(''); } -function getImagePathFromDocumentName(name: string): string { - let ext = FileUtils.getFileExtension(name); - let thumbnail = Configurator.getFileExtensionToImageMap()[ext]; - return FileUtils.getPathToImage(thumbnail); -} - function launchDocument(filename: string) { let fullPath = FileUtils.getPathToDocument(filename); shell.openItem(fullPath);