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/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 07e739e..73630a9 100644 --- a/src/assets/conf/resources-landing-page.json +++ b/src/assets/conf/resources-landing-page.json @@ -1,6 +1,9 @@ { "grid-container": { - + "Resources": { + "description": "Top level resources", + "cards": [] + }, "Human Resources": { "description": "Policies, recruitment, onboarding, benefits and compensation", "cards": [ @@ -69,8 +72,6 @@ } ] }, - - "Marketing": { "description": "Client-facing media, publications, public relations and advertising", "cards": [ @@ -139,8 +140,6 @@ } ] }, - - "Productivity": { "description": "Basic work tools, e-mail, calendar, document applications and cloud storage", "cards": [ @@ -174,8 +173,6 @@ } ] }, - - "Training": { "description": "Career growth, skills development, online courses, manuals and references", "cards": [ @@ -218,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 new file mode 100644 index 0000000..48aa54d --- /dev/null +++ b/src/assets/resources/coming-soon.pdf.json @@ -0,0 +1,4 @@ +{ + "description": "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 ba56d73..06654ab 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 } @@ -109,6 +108,66 @@ export class DocumentDirectory { root: DirectoryNode; + getCards(): Map { + 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(); + 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); + 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) { + sb = []; + } + sa.push(...sb); + a[key] = sa; + } + } + } export class FileNode { @@ -121,10 +180,63 @@ 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 + } + + private static getImagePathFromDocumentName(name: string): string { + let ext = FileUtils.getFileExtension(name); + let thumbnail = Configurator.getFileExtensionToImageMap()[ext]; + return thumbnail; + } + open() { shell.openItem(this.filePath); } + show() { + shell.showItemInFolder(this.filePath); + } + + toCard(): object { + let altProps = FileNode.loadAltProps(this.filePath); + let imageName = FileNode.getImagePathFromDocumentName(this.filePath); + let cardObj = { + "title": this.getTitle(), + "description": "", + "imagePath": imageName, + "urlText": this.filePath, + "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); + let ext = path.extname(name); + let cName = name.replace(ext, ""); + cName = cName.replace(/[\-._]/ig, " ") + return `${cName} (${ext.substr(1).toUpperCase()})` + } + + isDescriptor() { + + } + static compare(a: FileNode, b: FileNode): number { return a.filePath.localeCompare(b.filePath); } @@ -140,6 +252,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()) { @@ -167,6 +280,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 3e50911..f0fba9a 100644 --- a/src/ts_source/themes.ts +++ b/src/ts_source/themes.ts @@ -89,4 +89,4 @@ export module Themes { } } -Themes.initTheme(); +Themes.initTheme(); \ No newline at end of file diff --git a/src/ts_source/viewFactory.ts b/src/ts_source/viewFactory.ts index 6bf6084..4d1639e 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; const fs = require('fs'); @@ -20,29 +21,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]; @@ -50,11 +65,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 = { @@ -91,10 +110,17 @@ export function buildWebCardsFromConfig(configName: string) { collapseImg.attr("src", `../images/chevron-${newDirection}-${theme}.svg`); }); + 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, $); } + + } } @@ -135,12 +161,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); diff --git a/tests/fileutils-test.ts b/tests/fileutils-test.ts index 0513e92..d69f074 100644 --- a/tests/fileutils-test.ts +++ b/tests/fileutils-test.ts @@ -2,11 +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); + }); function testDocumentDirectoryFailNoExist() { @@ -24,9 +26,11 @@ function testDocumentDirectoryFailFile() { } function testDocumentDirectoryConstructor() { - let directoryPath = path.join(__dirname, "../src/assets/documents"); + let directoryPath = path.join(__dirname, "../src/assets/resources"); + let start = performance.now() let documents = new DocumentDirectory(directoryPath); - console.log(documents); - console.log((documents.root.getDirectories()[0].children)); + let end = performance.now() + console.log(documents.getCards()); + console.log(`Execution time: ${end-start}ms`) }