├── .gitattributes ├── .gitignore ├── Gruntfile.js ├── LICENSE ├── NOTICE ├── README.md ├── TempPatch ├── dxsync-1.0.2.tar.gz └── dxsync-1.0.3-1.tar.gz ├── dashboard.tar.gz ├── developer_readme.md ├── digexp-dashboard ├── .gitignore ├── .npmignore ├── README.md ├── bin │ └── dxdashboard ├── css │ └── app.css ├── dashboard-config.json ├── dashboard_index.html ├── data │ ├── JSON Module Contribution Schema v1.8.json │ ├── JSON Profile schema v1.2.json │ └── system_modules.json ├── js │ ├── app.js │ ├── ch_processes │ │ ├── watchApp.js │ │ └── watchBuild.js │ ├── controllers.js │ ├── controllers │ │ ├── addModuleController.js │ │ ├── appListController.js │ │ ├── cdnSuggestionsController.js │ │ ├── cloneThemeController.js │ │ ├── listThemesController.js │ │ ├── listWcmDesignsController.js │ │ ├── spConfigController.js │ │ ├── syncErrorController.js │ │ ├── themeModulesController.js │ │ ├── themeProfilesController.js │ │ ├── themesController.js │ │ ├── wcmDesignsController.js │ │ └── wcmErrorController.js │ ├── dashConfig.js │ ├── directives.js │ ├── imports.js │ ├── nav-bar.js │ ├── settings.js │ ├── spApp.js │ ├── themes.js │ ├── utils.js │ └── wcmDesign.js ├── package.json ├── partials │ ├── appDetailsView.html │ ├── listAppsView.html │ ├── listThemesView.html │ ├── listWcmDesignsView.html │ ├── modals │ │ ├── addModuleModal.html │ │ ├── cdnSuggestionsArea.html │ │ ├── cloneThemeModal.html │ │ ├── listThemesModal.html │ │ ├── listWcmDesignsModal.html │ │ ├── syncErrorModal.html │ │ ├── themeModulesModal.html │ │ ├── themeProfilesModal.html │ │ └── wcmErrorModal.html │ ├── nav-bar.html │ └── settingsView.html ├── postinstall.js ├── preinstall.js ├── spconfig │ ├── configbuild.json │ └── configlint.json ├── splogs │ └── readme └── tag-replacements.json ├── digexp-sp-server ├── .gitignore ├── README.md ├── index.js ├── package.json ├── script-portlet-server.js └── tag-replacements.json ├── digexp-wcm-design ├── .gitignore ├── bin │ ├── dxwcmdesigns │ └── wcmHelper ├── lib │ ├── utils.js │ ├── wcm-authenticated-request.js │ ├── wcmItem.js │ └── wcmOperations.js ├── package.json ├── readme.md ├── test │ ├── libraries │ │ ├── Design Library.json │ │ ├── Web Content Templates 3.0.json │ │ └── Web Content Templates 3.0 │ │ │ ├── Authoring Templates │ │ │ ├── Article-elements.json │ │ │ ├── Article-elements │ │ │ │ ├── Body_richtext.rtf │ │ │ │ └── preview-image_file.txt │ │ │ ├── Gws bestest-elements.json │ │ │ ├── Gws bestest-elements │ │ │ │ ├── Cr_reference.txt │ │ │ │ ├── Dt_date.txt │ │ │ │ ├── Filetest_file.txt │ │ │ │ ├── HTMl_html.html │ │ │ │ ├── JSP_jsp.txt │ │ │ │ ├── Link_link.txt │ │ │ │ ├── Number_number.txt │ │ │ │ ├── Opt_optionselection.txt │ │ │ │ ├── RichTexter_richtext.rtf │ │ │ │ ├── Short Text_short.txt │ │ │ │ ├── Text_text.txt │ │ │ │ ├── UsedSel_userselecttion.txt │ │ │ │ └── img_img.txt │ │ │ ├── Image-elements.json │ │ │ ├── Image-elements │ │ │ │ ├── Image_img.txt │ │ │ │ └── preview-image_file.txt │ │ │ ├── List-elements.json │ │ │ ├── List-elements │ │ │ │ ├── menu_reference.txt │ │ │ │ └── preview-image_file.txt │ │ │ ├── Rich Text-elements.json │ │ │ └── Rich Text-elements │ │ │ │ ├── body_richtext.rtf │ │ │ │ └── preview-image_file.txt │ │ │ ├── Components │ │ │ ├── 1106message.txt │ │ │ ├── 3297message.txt │ │ │ ├── 6161message.txt │ │ │ ├── 9785message.txt │ │ │ ├── Brief-IBM Acquires StrongLoop.pdf │ │ │ ├── HTML - Analytics.html │ │ │ ├── JSPER_jsp.txt │ │ │ ├── LibLink_link.txt │ │ │ ├── Now_date.txt │ │ │ ├── Number_number.txt │ │ │ ├── Preference JS.js │ │ │ ├── Rich.rtf │ │ │ ├── Style alt.css │ │ │ ├── Tefer_reference.txt │ │ │ ├── css file-file.css │ │ │ ├── fred.png │ │ │ └── icons │ │ │ │ ├── DeleteIcon - Copy.png │ │ │ │ ├── DeleteIcon.png │ │ │ │ ├── EditIcon.png │ │ │ │ └── InfoIcon48.png │ │ │ ├── Presentation Templates │ │ │ ├── Article.html │ │ │ ├── Image.html │ │ │ ├── List of Items.html │ │ │ ├── Message.html │ │ │ └── Rich Text.html │ │ │ └── Workflow Items │ │ │ └── Workflow Stages │ │ │ └── WStage_workflowstage.txt │ └── wcmHelper.js ├── wcmHelper.js ├── wcmHelperTest.js └── wcmdesigns.js ├── gulpfile.js ├── install.cmd ├── install.sh ├── package.json ├── release └── digexp-toolkit.zip ├── sp-server.tar.gz ├── uninstall.cmd ├── uninstall.sh └── wcm-design.tar.gz /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.cmd eol=crlf 4 | 5 | *.gitattributes eol=crlf 6 | 7 | *.zip binary 8 | *.gz binary 9 | *.md binary 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | **/npm-debug.log 4 | **/node_modules/** 5 | /build 6 | *.project -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | "use strict"; 3 | var exec = require("child_process").exec, fs = require("fs"); 4 | grunt.initConfig({ 5 | compress : { 6 | main : { 7 | options : { 8 | archive : "./build/digexp-toolkit.zip" 9 | }, 10 | files : [{ 11 | expand : true, 12 | cwd : ".", 13 | src : ["install.cmd", "install.sh", "uninstall.cmd", "uninstall.sh", "readme.md", "wcm-design.tar.gz", "dashboard.tar.gz", "sp-server.tar.gz", "LICENSE", "NOTICE"], 14 | dest : "/", 15 | filter : "isFile" 16 | }] 17 | } 18 | } 19 | }); 20 | grunt.loadNpmTasks("grunt-contrib-compress"); 21 | grunt.registerTask("default", []); 22 | grunt.registerTask("build", ["compress:main", "_build"]); 23 | /** 24 | * Builds the app 25 | */ 26 | grunt.registerTask("_build", function() { 27 | }); 28 | }; -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Web Developer Toolkit for IBM Digital Experience 2 | (C)Copyright 2015 IBM Corporation 3 | 4 | This product includes software contributed to 5 | OpenNTF Alliance (http://www.OpenNTF.org/) 6 | 7 | This product is licensed under the terms of the Apache 2.0 license. 8 | 9 | Third party code that the user must acquire: 10 | Angular version 1.3.0 11 | http://angularjs.org 12 | License: MIT 13 | 14 | Bootstrap version 3.2.0 15 | http://getbootstrap.com 16 | License: MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 17 | 18 | nwjs version 0.12.3 19 | Link: https://www.npmjs.com/package/nwjs 20 | License: MIT (https://www.npmjs.com/package/nwjs) 21 | 22 | Referenced Dependencies: 23 | adm-zip version 0.4.7 24 | Link: https://www.npmjs.com/package/adm-zip 25 | License: MIT (https://github.com/cthackers/adm-zip/blob/master/MIT-LICENSE.txt) 26 | Used in Dashboard 27 | 28 | anymatch version 1.3.0 29 | https://www.npmjs.com/package/anymatch 30 | License: ISC (https://github.com/es128/anymatch/blob/master/LICENSE) 31 | Used in Dashboard 32 | 33 | Async.js version 1.3.0 34 | https://www.npmjs.com/package/async 35 | License: MIT (https://github.com/caolan/async/blob/master/LICENSE) 36 | Used in: Dashboard 37 | 38 | Chokidar version 1.0.3 39 | https://www.npmjs.com/package/chokidar 40 | License: MIT (https://github.com/paulmillr/chokidar#license) 41 | Used in Dashboard 42 | 43 | Diff version 1.4.0 44 | https://www.npmjs.com/package/diff 45 | License: BSD-3-clause (https://github.com/kpdecker/jsdiff/blob/master/LICENSE) 46 | Used in Dashboard 47 | 48 | Dxsync (by IBM) 49 | https://github.com/digexp/dxsync 50 | License: Apache (https://github.com/digexp/dxsync/blob/master/LICENSE) 51 | Used in dashboard 52 | 53 | Express version 3.0.0 or greater 54 | https://www.npmjs.com/package/express 55 | License: MIT (https://github.com/strongloop/express) 56 | Used in SP-server 57 | 58 | Findit version 2.0.0 59 | https://www.npmjs.com/package/findit 60 | License: MIT (https://github.com/substack/node-findit/blob/master/package.json) 61 | Used in dashboard, WCM designs 62 | 63 | Graceful-fs version 3.0.6 64 | https://www.npmjs.com/package/graceful-fs 65 | License: ISC (https://github.com/isaacs/node-graceful-fs/blob/master/LICENSE) 66 | Used in WCM designs 67 | 68 | Hashmap version 2.0.3 69 | https://www.npmjs.com/package/hashmap 70 | License: MIT (https://github.com/flesler/hashmap/blob/master/LICENSE) 71 | Used in WCM designs 72 | 73 | MapStream version 0.0.6 74 | https://www.npmjs.com/package/map-stream 75 | License: MIT (https://github.com/dominictarr/map-stream/blob/master/LICENCE) 76 | Used in dashboard 77 | 78 | mkdirp version 0.5.1 79 | https://www.npmjs.com/package/mkdirp 80 | License: MIT (https://github.com/substack/node-mkdirp/blob/master/LICENSE) 81 | Used in dashboard 82 | 83 | Node-notifier v4.2.3 84 | https://www.npmjs.com/package/node-notifier 85 | License: MIT (https://github.com/mikaelbr/node-notifier#license) 86 | Used in dashboard 87 | 88 | Open v.0.0.5 89 | https://www.npmjs.com/package/open 90 | License: MIT (https://github.com/pwnall/node-open/blob/master/LICENSE) 91 | Used in dashboard 92 | 93 | q version 1.2.0 94 | https://www.npmjs.com/package/q 95 | License: MIT (https://github.com/kriskowal/q/blob/version 1/LICENSE) 96 | Used in WCM designs 97 | 98 | prompt 0.2.14 https://www.npmjs.com/package/prompt 99 | License: MIT 100 | https://github.com/flatiron/prompt/blob/master/LICENSE 101 | Used in WCM designs 102 | 103 | Request version 2.58.0 104 | https://www.npmjs.com/package/request 105 | License: Apache 2.0 (https://github.com/request/request/blob/master/LICENSE) 106 | Used in dashboard 107 | 108 | splint version 0.1.0 109 | https://github.com/OpenNTF/Script-Portlet-Node-Samples 110 | License: Apache License (https://github.com/OpenNTF/Script-Portlet-Node-Samples/blob/master/LICENSE) 111 | Used in dashboard 112 | 113 | Tracer version 0.7.4 114 | https://www.npmjs.com/package/tracer 115 | License: MIT (https://github.com/baryon/tracer#license) 116 | Used in dashboard, WCM designs 117 | 118 | Vinyl version 0.5.0 119 | https://www.npmjs.com/package/vinyl 120 | License: MIT (https://github.com/wearefractal/vinyl/blob/master/LICENSE) 121 | Used in dashboard 122 | 123 | Vinyl-fs version 1.0.0 124 | https://www.npmjs.com/package/vinyl-fs 125 | License: MIT (https://github.com/wearefractal/vinyl-fs/blob/master/LICENSE) 126 | Used in dashboard 127 | 128 | Yargs version 3.18.0 129 | https://www.npmjs.com/package/yargs 130 | License: MIT (https://github.com/bcoe/yargs/blob/master/LICENSE) 131 | Used in WCM designs 132 | 133 | -------------------------------------------------------------------------------- /TempPatch/dxsync-1.0.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/TempPatch/dxsync-1.0.2.tar.gz -------------------------------------------------------------------------------- /TempPatch/dxsync-1.0.3-1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/TempPatch/dxsync-1.0.3-1.tar.gz -------------------------------------------------------------------------------- /dashboard.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/dashboard.tar.gz -------------------------------------------------------------------------------- /developer_readme.md: -------------------------------------------------------------------------------- 1 | # Building the packages 2 | This information is only needed if you are updating source for this toolkit. 3 | 4 | There is a gulp script to automatically package the modules that go into this toolkit. To run the script, 5 | first install gulp globally: 6 | ``` 7 | $ npm install -g gulp 8 | ``` 9 | Then install the script's dependencies: 10 | ``` 11 | $ npm install 12 | ``` 13 | Then run 14 | ``` 15 | $ gulp 16 | ``` 17 | from the root directory of the repo to pack the modules and watch the files for changes. 18 | There are many files to watch so it may take about a minute for gulp to 19 | start watching. 20 | 21 | You can use 22 | ``` 23 | $ gulp pack 24 | ``` 25 | to just pack the files and 26 | ``` 27 | $ gulp watch 28 | ``` 29 | to just watch the files. Running `gulp watch` takes at least a minute to start. 30 | To build individual tarballs, you can use: 31 | ``` 32 | $ gulp pack_dashboard 33 | $ gulp pack_wcm 34 | $ gulp pack_sp_server 35 | ``` 36 | 37 | The tarballs should be repackaged before running `git commit` 38 | in order to update them. You can run `gulp pack` before pushing or have the gulp 39 | script run in the background. 40 | 41 | Also make sure that the gulp repackages the tarballs after 42 | pulling any changes from the git repo. The tarball's will not be committed 43 | after running `$ git pull` but the updated tarballs will be included in the next commit. 44 | 45 | To create the release zip install Grunt client 46 | 47 | npm install -g grunt-cli 48 | 49 | then run grunt build to generate the zip in the build directory. When you are releasing copy the zip to the release directory 50 | 51 | 52 | ## Note regarding dxsync 53 | A modified version of dxsync is included in the repo as TempPatch. This version 54 | of dxsync doesn't have any pre-compiled modules related to pathwatcher. 55 | 56 | ## File Watching 57 | In the dashboard, separate processes are spawned for watching files (to avoid 58 | using the same processes as the UI of the dashboard). The code for those processes 59 | can be found under `digexp-dashboard/js/ch_processes/`. STDIN and STDOUT are 60 | used for IPC due to issues with node-channels on windows. However, in retrospect, 61 | there are more robust options (such as TCP sockets). 62 | 63 | 64 | -------------------------------------------------------------------------------- /digexp-dashboard/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ################# 3 | ## node_modules 4 | ################# 5 | 6 | node_modules 7 | .project 8 | user-settings.json 9 | **/*.log 10 | **/*.*~ 11 | .idea/** 12 | predefined_modules/** -------------------------------------------------------------------------------- /digexp-dashboard/.npmignore: -------------------------------------------------------------------------------- 1 | user-settings.json -------------------------------------------------------------------------------- /digexp-dashboard/README.md: -------------------------------------------------------------------------------- 1 | # Web Developer Dashboard for IBM Digital Experience 2 | 3 | This package provides the dashboard user interface support for the Web Developer Toolkit for IBM Digital Experience. For more information, see the readme.md file for the toolkit. 4 | 5 | -------------------------------------------------------------------------------- /digexp-dashboard/bin/dxdashboard: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | var ch = require("child_process"); 4 | 5 | ch.exec("nw", { cwd: __dirname + "/.." }, function(err, stdout, stderr) { 6 | if (err) { 7 | console.error("ERROR"); 8 | if (stderr) { 9 | console.error(stderr); 10 | } 11 | console.error("Make sure that nw.js is installed"); 12 | console.error("run `npm install -g nw`"); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /digexp-dashboard/css/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | -webkit-user-select: none; /* Disables highlighting */ 3 | padding-right: 0px !important; 4 | } 5 | 6 | html { 7 | font-size: initial; 8 | box-sizing: border-box; 9 | overflow-y: hidden; 10 | } 11 | 12 | .dashboard-list { 13 | overflow-y: scroll; 14 | width: calc(100% + 15px); 15 | padding-right: 15px; 16 | padding-top: 15px; 17 | max-height: calc(100vh - 208px); 18 | min-height: calc(100vh - 208px); 19 | overflow-x: hidden; 20 | } 21 | .dashboard-list > .row { 22 | margin-right: 0px 23 | } 24 | 25 | .dashboard-list > .row > .col-lg-12, 26 | .dashboard-list > .row > .col-md-12, 27 | .dashboard-list > .row > .col-md-12 { 28 | padding-right: 0px 29 | } 30 | 31 | .navbar { 32 | margin-bottom: 10px 33 | } 34 | 35 | #dash-separator { 36 | margin-left: -15px; 37 | margin-right: -15px; 38 | border-bottom: 2px solid lightgray; 39 | } 40 | 41 | .view-header { 42 | margin-top: 10px; 43 | float: left; 44 | } 45 | 46 | .view-header-path { 47 | color: gray; 48 | float: right; 49 | font-size: 18px; 50 | margin-top: 10px; 51 | } 52 | 53 | .form-inline { 54 | margin-bottom: 10px; 55 | } 56 | 57 | .navbar-default { 58 | background-color: #325C80;/*#00649D; /*#008ABF; /*#2F5778;;*/ 59 | border: none; 60 | border-radius: 0px; 61 | } 62 | 63 | .navbar-default h1 { 64 | color: white; 65 | font-size: 32px; 66 | } 67 | 68 | #dash-nav-bar .nav { 69 | border: none 70 | } 71 | 72 | .nav > li > a { 73 | color: lightgray; 74 | } 75 | 76 | .nav > li > a:hover, .nav > li > a:focus { 77 | 78 | background-color: lightgray; 79 | border: 1px solid lightgray; 80 | border-bottom: none; 81 | color: #325C80; 82 | } 83 | 84 | .modal-body { 85 | min-height: 25vh; 86 | max-height: 75vh; 87 | overflow-y: auto; 88 | } 89 | 90 | 91 | .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th { 92 | padding-left: 0px; 93 | } 94 | 95 | #alert-wrapper { 96 | position: fixed; 97 | top: 0px; 98 | right: 0px; 99 | width: 400px; 100 | max-height: 100%; 101 | overflow-y: hidden; 102 | overflow-x: hidden; 103 | } 104 | 105 | #alert-wrapper .alert { 106 | margin: 0px; 107 | opacity: 1; 108 | } 109 | 110 | #alert-wrapper .alert:hover { 111 | opacity: 1.0; 112 | } 113 | 114 | 115 | .item-row { 116 | margin-bottom: 20px; 117 | padding-bottom: 20px; 118 | border-bottom: 1px solid lightgray; 119 | } 120 | 121 | .item-row img { 122 | float: right 123 | } 124 | 125 | @media (max-width: 1200px) { 126 | .container { 127 | margin: 0px; 128 | width: 100%; 129 | } 130 | } 131 | 132 | .btn-file { 133 | position: relative; 134 | overflow: hidden; 135 | } 136 | .btn-file input[type=file] { 137 | position: absolute; 138 | top: 0; 139 | right: 0; 140 | min-width: 100%; 141 | min-height: 100%; 142 | font-size: 100px; 143 | text-align: right; 144 | filter: alpha(opacity=0); 145 | opacity: 0; 146 | outline: none; 147 | background: white; 148 | cursor: inherit; 149 | display: block; 150 | } 151 | 152 | .loading { 153 | font-size: 36px; 154 | } 155 | 156 | .animate.ng-enter, 157 | .animate.ng-leave { 158 | -webkit-transition: 0.5s linear all; 159 | -mozansition: 0.5s linear all;; 160 | transition: 0.5s linear all;; 161 | } 162 | 163 | .animate-if.ng-enter, 164 | .animate-if.ng-leave.ng-leave-active { 165 | height: 0px; 166 | } 167 | 168 | .animate-if.ng-leave, 169 | .animate-if.ng-enter.ng-enter-active { 170 | height:40px; 171 | } 172 | 173 | @-webkit-keyframes rotating { 174 | from{ 175 | -webkit-transform: rotate(0deg); 176 | } 177 | to{ 178 | -webkit-transform: rotate(360deg); 179 | } 180 | } 181 | .loading-spinner { 182 | -webkit-animation: rotating 1.5s linear infinite; 183 | border-radius: 1000px; 184 | font-size: 18px; 185 | border: 3px solid white; 186 | } 187 | .syncing-spinner { 188 | -webkit-animation: rotating 1.5s linear infinite; 189 | } 190 | 191 | .theme-profile { 192 | position: relative; 193 | } 194 | 195 | .theme-profile-row:hover a { 196 | background-color: firebrick !important; 197 | border: 2px solid firebrick; 198 | border-radius: 2px !important; 199 | color: white !important; 200 | text-decoration: none; 201 | } 202 | 203 | #add-module-modal .control-label { 204 | padding-right: 0px !important; 205 | } 206 | 207 | .modal-body { 208 | overflow-y: scroll; 209 | } 210 | 211 | .tree-branch-offset { 212 | margin-left: 20px; 213 | } 214 | 215 | .ng-hide-add, .ng-hide-remove { 216 | display: block !important; 217 | } 218 | .slide-left { 219 | -webkit-transition: 5s linear all; 220 | transition: 5s linear all; 221 | } 222 | 223 | .fadein.ng-hide-remove { 224 | width: 0px; 225 | display: block !important; 226 | } 227 | .slide-left.ng-hide-remove.ng-hide-remove-active { 228 | width: 500px; 229 | } 230 | 231 | .glyphicon-check { 232 | color: green !important; 233 | } 234 | .glyphicon-unchecked { 235 | color: #999 !important; 236 | } 237 | 238 | .warning { 239 | color: orange; /*#f0ad4e;*/ 240 | } 241 | 242 | .cdn-suggestion { 243 | padding: 3px; 244 | padding-left: 5px; 245 | margin: 2px; 246 | } 247 | 248 | .cdn-suggestion:hover { 249 | background-color: #ededed; 250 | } 251 | 252 | /* Scrollbar */ 253 | 254 | ::-webkit-scrollbar { 255 | width: 10px; 256 | background-color:white; 257 | } 258 | ::-webkit-scrollbar-button { 259 | width: 8px; 260 | height:0px; 261 | } 262 | ::-webkit-scrollbar-track { 263 | background:#eee; 264 | border: thin solid lightgray; 265 | border-top: none; 266 | } 267 | ::-webkit-scrollbar-thumb { 268 | background:#ccc; 269 | border: thin solid #ccc; 270 | border-radius: 4px; 271 | } 272 | ::-webkit-scrollbar-thumb:hover { 273 | background: #ccc; 274 | } 275 | 276 | .dropdown-menu .no-a-tag { 277 | padding-left: 10px; 278 | padding-right: 10px; 279 | width: 200px; 280 | padding-bottom: 5px; 281 | } 282 | 283 | .dropdown-menu .server-settings-item { 284 | min-width: 360px; /** TODO better styling that stretches to fit text */ 285 | } 286 | 287 | .settingSmall{ 288 | padding: 3px; 289 | } 290 | 291 | .settingSmall:first-child { 292 | left-padding: 0px; 293 | } 294 | .settingWide { 295 | padding: 3px; 296 | } 297 | 298 | .module-item { 299 | margin-left: 10px; 300 | padding-left: 14px; 301 | padding-top: 5px; 302 | padding-bottom: 8px; 303 | border-left: 4px solid lightgray; 304 | margin-bottom: 10px; 305 | } 306 | 307 | .module-item:hover { 308 | background-color: #f7f7f7; 309 | } 310 | 311 | input.ng-invalid-pattern { 312 | -webkit-appearance: textfield; 313 | background-color: salmon; 314 | padding-top: 2px; 315 | padding-bottom: 2px; 316 | padding-left: 1px; 317 | padding-right: 1px; 318 | border-style: solid !important; 319 | border: 1px solid lightgray !important; 320 | } 321 | 322 | td:first-child, th:first-child { 323 | padding-left: 0px; 324 | } 325 | 326 | .small-input { 327 | padding:5px; 328 | padding-left:10px; 329 | border-radius:5px; 330 | border: 1px solid lightgray; 331 | width:100% 332 | } 333 | 334 | .active-module-category > a{ 335 | font-weight: bold !important; 336 | } -------------------------------------------------------------------------------- /digexp-dashboard/dashboard-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "servers": [ 3 | { 4 | "name": "Dashboard", 5 | "userName": "", 6 | "password": "", 7 | "port": "10039", 8 | "contenthandlerPath": "/wps/mycontenthandler", 9 | "host": "" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /digexp-dashboard/dashboard_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Web Developer Dashboard for IBM Digital Experience 17 | 18 | 19 | 20 |
21 | 22 |
23 |
24 |
25 |
26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /digexp-dashboard/data/JSON Module Contribution Schema v1.8.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "IBM WebSphere Portal JSON Module Contribution schema", 4 | "description": "A schema for use in a validator tool, to validate the syntax of WebSphere Portal Theme Optimization Framework module contributions", 5 | "type": "object", 6 | "properties": { 7 | "modules": { 8 | "$ref": "#/definitions/nonEmptyArrayOfModules" 9 | } 10 | }, 11 | "additionalProperties": false, 12 | "definitions": { 13 | "nonEmptyArrayOfModules": { 14 | "type": "array", 15 | "minItems": 1, 16 | "items": { 17 | "$ref": "#/definitions/moduleObject" 18 | }, 19 | "additionalItems": false, 20 | "uniqueItems": true 21 | }, 22 | "moduleObject": { 23 | "oneOf": [{ 24 | "type": "object", 25 | "properties": { 26 | "id": { 27 | "type": "string" 28 | }, 29 | "version": { 30 | "type": "string", 31 | "pattern": "^[0-9]*([.]?[0-9]+)*$" 32 | }, 33 | "prereqs": { 34 | "$ref": "#/definitions/nonEmptyArrayOfPrereqs" 35 | }, 36 | "contributions": { 37 | "$ref": "#/definitions/nonEmptyArrayOfContributions" 38 | }, 39 | "capabilities": { 40 | "type" : "array", 41 | "minItems" : 1, 42 | "items" : { 43 | "type": "object", 44 | "properties": { 45 | "id": { 46 | "type": "string" 47 | }, 48 | "value": { 49 | "type": "string", 50 | "pattern": "^[0-9]*([.]?[0-9]+)*$" 51 | } 52 | }, 53 | "additionalProperties": false, 54 | "required": ["id", 55 | "value"] 56 | }, 57 | "additionalItems" : false, 58 | "uniqueItems" : true 59 | } 60 | }, 61 | "required": ["id", 62 | "contributions"], 63 | "additionalProperties": false 64 | }, 65 | { 66 | "type": "object", 67 | "properties": { 68 | "id": { 69 | "type": "string" 70 | }, 71 | "version": { 72 | "type": "string", 73 | "pattern": "^[0-9]*([.]?[0-9]+)*$" 74 | }, 75 | "prereqs": { 76 | "$ref": "#/definitions/nonEmptyArrayOfPrereqs" 77 | }, 78 | "capabilities": { 79 | "type" : "array", 80 | "minItems" : 1, 81 | "items" : { 82 | "type": "object", 83 | "properties": { 84 | "id": { 85 | "type": "string" 86 | }, 87 | "value": { 88 | "type": "string", 89 | "pattern": "^[0-9]*([.]?[0-9]+)*$" 90 | } 91 | }, 92 | "additionalProperties": false, 93 | "required": ["id", 94 | "value"] 95 | }, 96 | "additionalItems" : false, 97 | "uniqueItems" : true 98 | } 99 | }, 100 | "required": ["id", 101 | "prereqs"], 102 | "additionalProperties": false 103 | }] 104 | }, 105 | "nonEmptyArrayOfPrereqs": { 106 | "type": "array", 107 | "minItems": 1, 108 | "items": { 109 | "$ref": "#/definitions/modulePrereq" 110 | }, 111 | "additionalItems": false, 112 | "uniqueItems": true 113 | }, 114 | "nonEmptyArrayOfContributions": { 115 | "type": "array", 116 | "minItems": 1, 117 | "items": { 118 | "$ref": "#/definitions/contribution" 119 | }, 120 | "additionalItems": false, 121 | "uniqueItems": true 122 | }, 123 | "modulePrereq": { 124 | "type": "object", 125 | "minProperties": 1, 126 | "maxProperties": 3, 127 | "properties": { 128 | "id": { 129 | "type": "string" 130 | }, 131 | "minVersion": { 132 | "type": "string", 133 | "pattern": "^[0-9]*([.]?[0-9]+)*$" 134 | }, 135 | "type": { 136 | "enum": ["optional", 137 | "required"] 138 | } 139 | }, 140 | "required": ["id"], 141 | "additionalProperties": false 142 | }, 143 | "contribution": { 144 | "type": "object", 145 | "oneOf": [{ 146 | "properties": { 147 | "type": { 148 | "enum": ["menu"] 149 | }, 150 | "sub-contributions": { 151 | "type": "array", 152 | "minItems": 1, 153 | "additionalItems": false, 154 | "uniqueItems": true, 155 | "items": { 156 | "type": "object", 157 | "properties": { 158 | "type": { 159 | "enum": ["json"] 160 | }, 161 | "ref-id": { 162 | "type": "string" 163 | }, 164 | "uris": { 165 | "$ref": "#/definitions/arrayOfUriTypesAndValues" 166 | } 167 | }, 168 | "required": ["type", "uris"], 169 | "additionalProperties" : false, 170 | "minProperties" : 2, 171 | "maxProperties" : 3 172 | } 173 | } 174 | }, 175 | "required": ["type", 176 | "sub-contributions"], 177 | "additionalProperties": false, 178 | "uniqueItems": true 179 | }, 180 | { 181 | "properties": { 182 | "type": { 183 | "enum": ["xslt"] 184 | }, 185 | "sub-contributions": { 186 | "type": "array", 187 | "minItems": 1, 188 | "additionalItems": false, 189 | "uniqueItems": true, 190 | "items": { 191 | "type": "object", 192 | "properties": { 193 | "type": { 194 | "enum": ["xslt"] 195 | }, 196 | "ref-id": { 197 | "type": "string" 198 | }, 199 | "uris": { 200 | "$ref": "#/definitions/arrayOfUriTypesAndValues" 201 | } 202 | }, 203 | "required": ["type", "uris"], 204 | "additionalProperties" : false, 205 | "minProperties" : 2, 206 | "maxProperties" : 3 207 | } 208 | } 209 | }, 210 | "required": ["type", 211 | "sub-contributions"], 212 | "additionalProperties": false, 213 | "uniqueItems": true 214 | }, 215 | { 216 | "properties": { 217 | "type": { 218 | "enum": ["head"] 219 | }, 220 | "sub-contributions": { 221 | "type": "array", 222 | "minItems": 1, 223 | "additionalItems": false, 224 | "uniqueItems": true, 225 | "items": { 226 | "type": "object", 227 | "properties": { 228 | "type": { 229 | "enum": ["css", 230 | "js"] 231 | }, 232 | "ref-id": { 233 | "type": "string" 234 | }, 235 | "uris": { 236 | "$ref": "#/definitions/arrayOfUriTypesAndValues" 237 | } 238 | }, 239 | "required": ["type", "uris"], 240 | "additionalProperties" : false, 241 | "minProperties" : 2, 242 | "maxProperties" : 3 243 | } 244 | } 245 | }, 246 | "required": ["type", 247 | "sub-contributions"], 248 | "additionalProperties": false, 249 | "uniqueItems": true 250 | }, 251 | { 252 | "properties": { 253 | "type": { 254 | "enum": ["config"] 255 | }, 256 | "sub-contributions": { 257 | "type": "array", 258 | "minItems": 1, 259 | "additionalItems": false, 260 | "uniqueItems": true, 261 | "items": { 262 | "type": "object", 263 | "properties": { 264 | "type": { 265 | "enum": ["js", 266 | "markup", 267 | "config_static", 268 | "config_dynamic"] 269 | }, 270 | "ref-id": { 271 | "type": "string" 272 | }, 273 | "uris": { 274 | "$ref": "#/definitions/arrayOfUriTypesAndValues" 275 | } 276 | }, 277 | "required": ["type", "uris"], 278 | "additionalProperties" : false, 279 | "minProperties" : 2, 280 | "maxProperties" : 3 281 | } 282 | } 283 | }, 284 | "required": ["type", "sub-contributions"], 285 | "additionalProperties": false, 286 | "uniqueItems": true 287 | }] 288 | }, 289 | "arrayOfUriTypesAndValues": { 290 | "type": "array", 291 | "minItems": 1, 292 | "additionalItems": false, 293 | "uniqueItems": true, 294 | "items": { 295 | "type": "object", 296 | "properties": { 297 | "value": { 298 | "type": "string", 299 | "format": "uri" 300 | }, 301 | "deviceClass": { 302 | "type": "string" 303 | }, 304 | "type": { 305 | "enum": ["debug", 306 | "rtl", 307 | "rtl,debug", 308 | "debug,rtl"] 309 | }, 310 | "lang": { 311 | "type": "string" 312 | } 313 | }, 314 | "additionalProperties": false, 315 | "required": ["value"] 316 | } 317 | } 318 | } 319 | } -------------------------------------------------------------------------------- /digexp-dashboard/data/JSON Profile schema v1.2.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "IBM WebSphere Portal JSON Theme Profile schema", 4 | "description": "A schema for use in a validator tool, to validate the syntax of WebSphere Portal Theme Optimization Framework profile definitions", 5 | "type": "object", 6 | "anyOf" : [ 7 | { "required" : ["moduleIDs"] }, 8 | { "required" : ["deferredModuleIDs"] } 9 | ], 10 | "properties" : { 11 | "moduleIDs" : { "$ref" : "#/definitions/nonEmptyArrayOfNonNullModuleIDs" }, 12 | "deferredModuleIDs" : { "$ref" : "#/definitions/nonEmptyArrayOfNonNullModuleIDs" }, 13 | "titles" : { "$ref" : "#/definitions/titlesOrDescriptions" }, 14 | "descriptions" : { "$ref" : "#/definitions/titlesOrDescriptions" }, 15 | "metadata" : {"$ref" : "#/definitions/metadata"} 16 | }, 17 | "additionalProperties" : false, 18 | "definitions" : { 19 | "nonEmptyArrayOfNonNullModuleIDs" : { 20 | "type" : "array", 21 | "minItems" : 1, 22 | "items" : { 23 | "type" : "string" 24 | }, 25 | "uniqueItems" : true 26 | }, 27 | "titlesOrDescriptions" : { 28 | "type" : "array", 29 | "minItems" : 1, 30 | "items" : { 31 | "minProperties" : 2, 32 | "properties" : { 33 | "lang" : {"type" : "string"} , 34 | "value" : {"type" : "string"} 35 | }, 36 | "required" : ["lang", "value"], 37 | "additionalProperties" : false, 38 | "uniqueItems" : true 39 | } 40 | }, 41 | "metadata" : { 42 | "minProperties" : 1, 43 | "additionalProperties" : false, 44 | "patternProperties" : { 45 | "[^metadata]" : {} 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /digexp-dashboard/js/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | // Main application with dependencies 11 | var dashboardApp = angular.module('dashboardApp', 12 | ['ngRoute', 'dashboardApp.navBar','dashboardControllers', 'ngAnimate']); 13 | var firstRoute = true; 14 | var digExperienceDashboard = 'Digital Experience Dashboard'; 15 | // Configure routes for the different views 16 | dashboardApp.config(['$compileProvider', 17 | function($compileProvider) { 18 | $compileProvider.imgSrcSanitizationWhitelist(/^\s*((https?|ftp|file|blob|chrome-extension):|data:image\/)/); 19 | $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file:chrome-extension):/); 20 | }]); 21 | dashboardApp.config(['$routeProvider', function($routeProvider) { 22 | var redirect = '/listApps'; 23 | if(firstRoute == true){ 24 | firstRoute = false; 25 | var configInfo = dashConfig.getConfigInfo(); 26 | var haveServers = configInfo.servers[0].host.length!= 0; 27 | // first start up and no routes go to settings 28 | if(haveServers == false){ 29 | redirect = '/settings'; 30 | } 31 | else{ 32 | redirect = configInfo.lastOpened; 33 | if(!redirect) 34 | redirect = '/listApps'; 35 | } 36 | 37 | } 38 | $routeProvider.when('/listApps', { 39 | templateUrl: 'partials/listAppsView.html' 40 | ,controller: 'AppsListController' 41 | }).when('/appDetails/:id', { 42 | templateUrl: 'partials/appDetailsView.html' 43 | // , controller : 'AppDetailsController' 44 | }).when('/settings', { 45 | templateUrl: 'partials/settingsView.html' 46 | ,controller: 'SettingsController' 47 | }).when('/listThemes', { 48 | templateUrl: 'partials/listThemesView.html' 49 | ,controller: 'ThemeListController' 50 | }).when('/listWcmDesigns', { 51 | templateUrl: 'partials/listWcmDesignsView.html' 52 | ,controller: 'WcmDesignListController' 53 | }).otherwise({ 54 | redirectTo: redirect 55 | }); 56 | }]); 57 | -------------------------------------------------------------------------------- /digexp-dashboard/js/ch_processes/watchApp.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | process.title = "digexp-dashboard watch"; 11 | 12 | var chokidar = require("chokidar"); 13 | var exec = require("child_process").exec; 14 | var anymatch = require("anymatch"); 15 | 16 | var directory = process.argv[2]; 17 | var buildCommand = process.argv[3] || ""; 18 | var server = JSON.parse(process.argv[4] || "{}"); 19 | var toIgnore = process.argv[5] || ""; 20 | toIgnore = toIgnore.split(";"); 21 | 22 | var length = toIgnore.length; 23 | for (var i = 0; i < length; i++) { 24 | if (toIgnore[i].match(/^[\/\\\w]+$/)) { 25 | toIgnore = toIgnore.concat(toIgnore[i] + "/**"); 26 | } 27 | } 28 | 29 | console.log("args: " + process.argv); 30 | console.log("server args:"); 31 | console.log(server); 32 | console.log("ignoring:" + toIgnore); 33 | 34 | // TODO not duplicate from app controller 35 | var makeServerArgs = function() { 36 | // todo https or http 37 | var args = ""; 38 | if (server.host || server.port) { 39 | args += " -scriptPortletServer http://" + server.host + ":" + server.port; 40 | } 41 | if (server.userName && server.password) { 42 | args += " -portalUser " + server.userName + " -portalPassword " + server.password; 43 | } 44 | return args; 45 | }; 46 | 47 | var build = function(cb) { 48 | exec(buildCommand, { cwd: directory }, function(err, stdout, stderr) { 49 | if (err) console.warn("watch build" + err); 50 | if (stdout) console.log("watch build" + stdout); 51 | if (stderr) console.warn("watch build" + stderr); 52 | 53 | cb && cb(); 54 | }); 55 | }; 56 | 57 | var push = function() { 58 | var sp = "sp"; 59 | if (process.platform !== "win32") { 60 | sp += ".sh"; 61 | } 62 | 63 | exec(sp + ' push -contentRoot "' + directory + '"' + makeServerArgs(), { cwd: directory }, 64 | function(err, stdout, stderr) { 65 | if (err) console.warn("watch push" + stderr); 66 | if (stdout) console.log("watch push" + stdout); 67 | if (stderr) console.warn("watch push" + stderr); 68 | }); 69 | }; 70 | 71 | var run = function(path) { 72 | if (path.match(/node\-modules|sp-cmdln\.log/) 73 | || anymatch(toIgnore, path)) { 74 | return; 75 | } 76 | console.log(path); 77 | console.log("push_starting, " + path + " modified"); 78 | if (buildCommand) { 79 | build(push); 80 | } else { 81 | push(); 82 | } 83 | }; 84 | 85 | var watcher = chokidar.watch(directory, { 86 | persistent: true, 87 | ignoreInitial: true, 88 | cwd: directory 89 | }); 90 | watcher.on("add", run); 91 | watcher.on("change", run); 92 | watcher.on("unlink", run); 93 | 94 | process.on("SIGTERM", function() { watcher.close(); }); 95 | process.on("exit", function() { watcher.close(); }); 96 | 97 | -------------------------------------------------------------------------------- /digexp-dashboard/js/ch_processes/watchBuild.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | process.title = "digexp-dashboard watch"; // I don't think that this does anything with ch.exec 11 | 12 | var chokidar = require("chokidar"); 13 | var exec = require("child_process").exec; 14 | var anymatch = require("anymatch"); 15 | 16 | var directory = process.argv[2]; 17 | var buildCommand = process.argv[3] || ""; 18 | var toIgnore = process.argv[4] || ""; 19 | toIgnore = toIgnore.split(";"); 20 | 21 | var length = toIgnore.length; 22 | for (var i = 0; i < length; i++) { 23 | // eg: src/js -> src/js/**, for anymatch 24 | if (toIgnore[i].match(/^[\/\\\w]+$/)) { 25 | toIgnore = toIgnore.concat(toIgnore[i] + "/**"); 26 | } 27 | } 28 | 29 | console.log("watching " + directory); 30 | 31 | var run = function(event, path) { 32 | if (path.match(/^\.hashes|\.conflict$/) // dxsync changes this file 33 | || anymatch(toIgnore, path)) { 34 | return; 35 | } 36 | 37 | if (event === "change" || event === "add" || event === "addDir") { 38 | console.log("path_changed:" + path); 39 | } else if (event === "unlink") { 40 | console.log("unlink:" + path); 41 | } 42 | 43 | if (buildCommand.length) { 44 | exec(buildCommand, function() { 45 | // console.log("waiting") 46 | }); 47 | } else { 48 | // console.log("waiting"); 49 | } 50 | }; 51 | 52 | var watcher = chokidar.watch(directory, { 53 | persistent: true, 54 | ignoreInitial: true, 55 | cwd: directory 56 | }); 57 | watcher.on("all", run); 58 | //watcher.on("unlinkDir", run); 59 | 60 | process.on("SIGTERM", function() { watcher.close() }); 61 | process.on("exit", function() { watcher.close() }); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | // Controllers - for list, details, and update views 11 | var dashboardControllers = angular.module('dashboardControllers', []); 12 | 13 | //Controller for Settings view 14 | dashboardControllers.controller('SettingsController', ['$scope', '$location', '$route', 15 | function($scope, $location, $route) { 16 | 17 | $scope.changed = false; // todo this should persist when the route changes 18 | // deep copy of the config 19 | $scope.configInfo = JSON.parse(JSON.stringify(dashConfig.getConfigInfo())); 20 | 21 | $scope.getServers = function(){ 22 | return $scope.configInfo.servers; 23 | }; 24 | 25 | $scope.servers = $scope.getServers(); 26 | $scope.activeServer = $scope.configInfo.spAppServer || "Dashboard"; 27 | 28 | $scope.getServersForSelect = function(){ 29 | var rVal = []; 30 | var servers = $scope.servers; 31 | if(servers != undefined) 32 | servers.forEach(function (server){ 33 | rVal.push({ServerId: server.name, ServerName: server.name}); 34 | }); 35 | return rVal; 36 | }; 37 | $scope.selectServers=$scope.getServersForSelect(); 38 | $scope.addServer = function(index){ 39 | var servers = $scope.servers; 40 | var server = {}; 41 | var name = servers[index].name; 42 | var nums = +(name.match(/\d+$/) || [-1])[0] + 1; 43 | 44 | server.name = name.replace(/\d+$/, "") + nums; 45 | server.userName = servers[index].userName; 46 | server.password = servers[index].password; 47 | server.host = servers[index].host; 48 | server.contenthandlerPath = servers[index].contenthandlerPath; 49 | server.port = servers[index].port; 50 | servers.push(server); 51 | $scope.servers = servers; 52 | $scope.selectServers=$scope.getServersForSelect(); 53 | }; 54 | 55 | $scope.removeServer = function(sName){ 56 | var servers = $scope.getServers(); 57 | var aServerOpts = document.querySelector("#activeServer").options; 58 | var count = 0; 59 | if(servers != undefined) 60 | servers.forEach(function(server){ 61 | if(sName == server.name){ 62 | servers.splice(count,1); 63 | aServerOpts.remove(count); 64 | } 65 | count++; 66 | }); 67 | }; 68 | $scope.updateServerName = function(index, value){ 69 | if($scope.selectServers[index].ServerName != value){ 70 | if($scope.activeServer == $scope.selectServers[index].ServerName) 71 | $scope.activeServer = value; 72 | var aServerOpt = document.querySelector("#activeServer").options[index]; 73 | $scope.selectServers[index].ServerName = aServerOpt.innerText = value; 74 | $scope.selectServers[index].ServerId = aServerOpt.label= value; 75 | } 76 | }, 77 | $scope.disableAddButton = function(index){ 78 | // did this way because sometimes the index # is greater than the length 79 | return index < $scope.servers.length-1; 80 | }; 81 | 82 | $scope.disableDeleteButton = function(index){ 83 | return index === 0; 84 | }; 85 | 86 | $scope.update = function() { 87 | settings.update(); 88 | 89 | $scope.changed = false; 90 | if ($scope.$parent) { 91 | $scope.$parent.changed = false; 92 | } 93 | }; 94 | 95 | /** 96 | * 97 | * @param pathProperty ('spAppPath'|'dxThemePath'|'wcmDesignsPath') 98 | */ 99 | $scope.setPath = function(pathProperty) { 100 | // this selects the correct folder but scrolls to the parent directory 101 | // todo scroll to the correct directory, might be an issue with nw.js itself 102 | $("#fileDialog").attr("nwWorkingDir", $scope.configInfo[pathProperty] || ""); 103 | 104 | $("#fileDialog").off(); 105 | $("#fileDialog").on("change", function() { 106 | $scope.configInfo[pathProperty] = $("#fileDialog").val(); 107 | $scope.changed = true; 108 | $scope.$apply(); 109 | }); 110 | 111 | $("#fileDialog").click(); 112 | }; 113 | 114 | $scope.$on('$routeChangeStart', function(event, newPath) { 115 | if ($scope.changed) { 116 | $('#unsaved-settings-modal').modal("show"); 117 | $('.modal-backdrop').remove(); 118 | event.preventDefault(); 119 | newPath = newPath.$$route.originalPath; 120 | 121 | $("#continue-without-saving-btn").off(); 122 | $("#continue-without-saving-btn").on("click", function() { 123 | $('#unsaved-settings-modal').modal("hide"); 124 | $('body').removeClass('modal-open'); 125 | setTimeout(function() { 126 | $location.url(newPath); 127 | $route.reload(); 128 | $('body').removeClass('modal-open'); 129 | $('.modal-backdrop').remove(); 130 | }, 50); 131 | setTimeout(function() { 132 | $('body').removeClass('modal-open'); 133 | }, 150); 134 | 135 | }); 136 | 137 | $("#save-and-continue-btn").off(); 138 | $("#save-and-continue-btn").on("click", function() { 139 | $('#unsaved-settings-modal').modal("hide"); 140 | $('body').removeClass('modal-open'); 141 | setTimeout(function() { 142 | $location.url(newPath); 143 | $route.reload(); 144 | // todo save settings asynchronously 145 | settings.update(); 146 | $('body').removeClass('modal-open'); 147 | $('.modal-backdrop').remove(); 148 | }); 149 | setTimeout(function() { 150 | $('body').removeClass('modal-open'); 151 | }, 150); 152 | }); 153 | 154 | location.hash = "#" + newPath; 155 | } 156 | }); 157 | } 158 | ]); 159 | -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/cdnSuggestionsController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('CdnSuggestionsController', ['$scope', function($scope) { 11 | 12 | var $parent = $scope.$parent; 13 | 14 | $scope.cdnSuggestions = []; 15 | $scope.activeSuggestion = {}; 16 | $scope.showingOptions = false; 17 | $scope.loading = 0; 18 | 19 | $scope.$on("newModuleUrlsChanged", function(event, args) { 20 | $scope.updateCdnSuggestions(args); 21 | }); 22 | 23 | $scope.updateCdnSuggestions = function(query) { 24 | console.log("query: " + query); 25 | 26 | 27 | if (query.length < 2 || query[query.length - 1] == ";") { 28 | $scope.cdnSuggestions = []; 29 | } else if (query.match(/(;|^)\w+$/)) { 30 | // TODO optimize split 31 | query = query.split(";"); 32 | query = query[query.length - 1]; 33 | 34 | request = request || require("request"); 35 | request("http://api.cdnjs.com/libraries?search=" + query + 36 | "&fields=version", function(error, response, body) { 37 | if (!error && response.statusCode == 200) { 38 | // don't show the results if the query changed 39 | if ($scope.newModule.urls.length > 0) { 40 | $scope.cdnSuggestions = JSON.parse(body).results; 41 | $scope.$apply(); 42 | } 43 | } 44 | }); 45 | } 46 | }; 47 | 48 | /** 49 | * For sorting autocomplete suggestions 50 | */ 51 | $scope.suggestionScore = function(suggestion) { 52 | if (!suggestion || !suggestion.name || !suggestion.name.length) { 53 | return 0; 54 | } else { 55 | // todo this is a special case 56 | if (suggestion.name === "twitter-bootstrap") { 57 | return 0; 58 | } 59 | var score = suggestion.name.length; 60 | // angularjs should suggested above of angularui (so it gets a lower score) 61 | if (suggestion.name[score - 2] === "j" && suggestion.name[score - 1] === "s") { 62 | score = score * 2 - 1; 63 | } else { 64 | score *= 2; 65 | } 66 | return score; 67 | } 68 | }; 69 | 70 | $scope.loadSuggestionOptions = function(suggestion) { 71 | $parent.newModule.urls = $parent.newModule.urls.replace(/[^;]+$/, "$`" + suggestion.latest); 72 | $scope.cdnSuggestions = []; 73 | //scope.showingOptions = true; 74 | //request("http://api.cdnjs.com/libraries?search=" + suggestion.name + 75 | // "&fields=assets", function(error, response, body) { 76 | // if (!error && response.statusCode == 200) { 77 | // // don't show the results if the query changed 78 | // if ($scope.newModule.urls.length > 0) { 79 | // var results = JSON.parse(body).results; 80 | 81 | // for (var i in results) { 82 | // if (results[i].name == suggestion.name) { 83 | // $scope.activeSuggestion = results[i]; 84 | // } 85 | // } 86 | // $scope.$apply(); 87 | // } 88 | // } 89 | //}); 90 | }; 91 | 92 | $scope.appendUrls = function(asset) { 93 | // var base = "https://cdnjs.cloudflare.com/ajax/libs/" + $scope.activeSuggestion.name 94 | // + "/" + asset.version + "/"; 95 | // var cdnUrls = asset.files.map(function(file) { 96 | // return base + file 97 | // }); 98 | // console.log($parent.newModule.urls); 99 | // console.log($parent.newModule.urls.replace(/([^;]+)$/, "$`" + cdnUrls.join(";"))); 100 | // $parent.newModule.urls = $parent.newModule.urls.replace(/([^;]+)$/, "$`" + cdnUrls.join(";")); 101 | $parent.newModule.urls = $parent.newModule.urls.replace(/[^;]+$/, 102 | "$`" + $scope.activeSuggestion.name + "/" + asset.version 103 | ) 104 | } 105 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/listThemesController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('ListThemesController', ['$scope', function($scope) { 11 | var $parent = $scope.$parent; 12 | 13 | $scope.serverThemes = []; 14 | 15 | $scope.submitted = false; 16 | 17 | $scope.host = ""; 18 | 19 | $scope.error = {}; // if there is an error 20 | $scope.server = dashConfig.getServerForTool(dashConfig.tools.dxTheme); 21 | 22 | $scope.portalConfig = { 23 | username: $scope.server.userName, 24 | password: $scope.server.password, 25 | host: $scope.server.host, 26 | port: $scope.server.port, 27 | contenthandlerPath: $scope.server.contenthandlerPath, 28 | secure: $scope.server.secure 29 | }; 30 | 31 | var init = function() { 32 | $scope.themeHosts = {}; 33 | for (var key in $parent.themes) { 34 | var theme = $parent.themes[key].theme; 35 | $scope.themeHosts[theme] = $scope.themeHosts[theme] || []; 36 | try { 37 | $scope.themeHosts[theme].push($parent.themes[key].settings.host); 38 | } catch (e) { 39 | $scope.themeHosts[theme].push(true); 40 | } 41 | } 42 | 43 | /** 44 | * @param name is 'theme' in .settings 45 | */ 46 | $scope.themeExists = function(name, host) { 47 | // TODO cache result 48 | if (!($scope.themeHosts[name] || "").length) { 49 | return false; 50 | } 51 | for (var i in $scope.themeHosts[name]) { 52 | if ($scope.themeHosts[name][i] === host) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | }; 58 | 59 | $scope.folderIsTaken = function(theme) { 60 | var folder = $scope.folders[theme]; 61 | return folder && (!$scope.themeExists(theme, $scope.host) && 62 | ($scope.existingFolders[folder])); 63 | }; 64 | 65 | $scope.folderIsValid = function(theme) { 66 | var folder = $scope.folders[theme]; 67 | return $scope.themeExists(theme, $scope.host) || 68 | (folder && !$scope.existingFolders[folder] && folder.match(/^[\w\d_-]+$/)); 69 | }; 70 | 71 | $scope.folders = {}; 72 | for (var key in $scope.themes) { 73 | if ($scope.themeExists($parent.themes[key].theme, $scope.host) 74 | && $parent.themes[key].settings.host === $scope.host) { 75 | 76 | $scope.folders[$parent.themes[key].theme] = $parent.themes[key].folder; 77 | } 78 | } 79 | $scope.existingFolders = {}; 80 | for (var key in $scope.themes) { 81 | $scope.existingFolders[key] = true; 82 | } 83 | }; 84 | 85 | 86 | $scope.dxsyncInit = function() { 87 | var conf = JSON.parse(JSON.stringify($scope.portalConfig)); // TODO 88 | 89 | if (conf.host[conf.host.length - 1] === "/") { 90 | conf.host = conf.host.substr(0, conf.host.length - 1); 91 | } 92 | $scope.host = conf.host; 93 | 94 | if (!$scope.submitted) { 95 | dxsync = dxsync || require("dxsync"); 96 | var listThemes = dxsync.getPromptSchema().basic[2].theme.valuesFn; 97 | debugLogger.log("starting to download list of themes"); 98 | 99 | $("#list-themes-first-button").attr("disabled", "disabled").html("Loading ..."); 100 | 101 | init(); 102 | listThemes(conf) 103 | .then(function(filenames) { 104 | debugLogger.log("Done downloading list of themes"); 105 | $scope.serverThemes = filenames; 106 | $scope.error.exists = false; 107 | debugLogger.log($scope.serverThemes); 108 | $scope.submitted = true; 109 | $scope.$apply(); 110 | $("#list-themes-first-button").removeAttr("disabled").html("View Themes"); 111 | }) 112 | .catch(function(err) { 113 | $scope.error = err; 114 | $scope.error.exists = true; 115 | $scope.submitted = true; 116 | console.error(err); 117 | $scope.$apply(); 118 | }); 119 | } else { 120 | $scope.getNewThemes().forEach($scope.addTheme); 121 | $("#list-themes-modal").modal("hide"); 122 | $scope.submitted = false; 123 | } 124 | }; 125 | 126 | $scope.getNewThemes = function() { 127 | return $scope.serverThemes 128 | .filter(function(t) { 129 | return !$scope.themeExists(t, $scope.host) 130 | && $scope.folders[t] 131 | && !$scope.existingFolders[$scope.folders[t]]; 132 | }); 133 | }; 134 | 135 | $scope.addTheme = function(theme) { 136 | var conf = JSON.parse(JSON.stringify($scope.portalConfig)); 137 | conf.theme = theme; 138 | $scope.folders[theme] = $scope.folders[theme].replace(/[^\w\d_\. -]/g, "_"); 139 | var folder = $scope.folders[theme]; 140 | fs.mkdir($scope.configInfo.dxThemePath + "/" + folder, 141 | function(err) { 142 | if (err) { 143 | console.warn(err); 144 | } else { 145 | dxsync = dxsync || require("dxsync"); 146 | dxsync.saveConfig($scope.configInfo.dxThemePath + "/" + folder, conf, function(error) { 147 | if (error) { 148 | console.warn(error); 149 | } else { 150 | // TODO loading bar while dir is being written 151 | themes.getThemes(); // this will load the theme into memory, todo optimize 152 | 153 | $scope.$parent.themes[folder] = $scope.$parent.themes[folder] || {}; 154 | $scope.$parent.themes[folder].needsToBeSynced = true; 155 | $scope.themeHosts[theme] = $scope.host; 156 | $scope.existingFolders[folder] = true; 157 | // delete $scope.folders[theme]; 158 | $scope.$apply(); 159 | } 160 | }); 161 | } 162 | }); 163 | }; 164 | 165 | 166 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/listWcmDesignsController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var debugLogger = utils.debugLogger('dashboard-apps'); 11 | dashboardControllers.controller('ListWcmDesignsController', ['$scope', 12 | function($scope) { 13 | var $parent = $scope.$parent; 14 | 15 | $scope.serverLibraries = []; 16 | 17 | $scope.submitted = false; 18 | $scope.error = {}; // if there is an error 19 | $scope.error.exists = false; 20 | 21 | $scope.server = dashConfig.getServerForTool(dashConfig.tools.wcmDesigns); 22 | $scope.portalConfig = { 23 | username : $scope.server.userName, 24 | password : $scope.server.password, 25 | host : $scope.server.host, 26 | port : $scope.server.port, 27 | secure : $scope.server.secure, 28 | contenthandlerPath : $scope.server.contenthandlerPath 29 | }; 30 | 31 | $scope.libraryExists = {}; 32 | for (var key in $scope.wcmDesigns) { 33 | $scope.libraryExists[$parent.wcmDesigns[key].title] = true; 34 | } 35 | 36 | $scope.getAndSync = function() { 37 | debugLogger.log($scope.submitted); 38 | 39 | var conf = JSON.parse(JSON.stringify($scope.portalConfig)); 40 | 41 | debugLogger.log(!$scope.submitted); 42 | if (!$scope.submitted) { 43 | // debugLogger.log(conf); 44 | debugLogger.log("starting to download list of libraries"); 45 | 46 | $("#list-libraries-first-button").attr("disabled", "disabled").html("Loading ..."); 47 | 48 | // get Libraries 49 | try { 50 | wcmHelper.getLibraries().then(function(libraries) { 51 | libraries.forEach(function(lib) { 52 | lib.title = lib.title.value || lib.title; 53 | lib.nm = lib.title.split(" ").join("_"); 54 | }); 55 | debugLogger.log("Done downloading list of libraries"); 56 | $scope.error.exists = false; 57 | $scope.submitted = true; 58 | $scope.serverLibraries = libraries; 59 | $scope.$apply(); 60 | $("#list-libraries-first-button").removeAttr("disabled").html("View Libraries"); 61 | debugLogger.log("ready to list libraries"); 62 | },function(err){ 63 | if(err.code == undefined) 64 | try{ 65 | err = JSON.parse(err.message); 66 | }catch(e){ 67 | err = {'responseText': err}; 68 | }; 69 | $scope.error = err; 70 | $scope.error.exists = true; 71 | $scope.submitted = true; 72 | debugLogger.log(err); 73 | $scope.$apply(); 74 | }); 75 | } catch(err) { 76 | $scope.error = err; 77 | $scope.error.exists = true; 78 | $scope.submitted = true; 79 | debugLogger.log(err); 80 | $scope.$apply(); 81 | } 82 | } else { 83 | $scope.serverLibraries.filter(function(t) { 84 | return !$scope.libraryExists[t]; 85 | }).filter(function(t) { 86 | dLib = document.getElementById(t.nm + "-path"); 87 | if (dLib != undefined) 88 | return dLib.checked; 89 | else 90 | return false; 91 | }).map($scope.addLibrary); 92 | $("#list-libraries-modal").modal("hide"); 93 | $scope.submitted = false; 94 | } 95 | }; 96 | 97 | $scope.addLibrary = function(library) { 98 | debugLogger.log(library); 99 | $parent.$parent.loadingNewLibraries++; 100 | $parent.$parent.status = 'Pulling Library ' + library.title; 101 | var options = { 102 | includeMeta : false, 103 | filterComponentId: true 104 | }; 105 | library.datePulled = Date(); 106 | var title = library.title.value || library.title; 107 | wcmHelper.pullLibrary(title, options).then(function() { 108 | $scope.libraryExists[library.title] = true; 109 | $parent.$parent.loadingNewLibraries--; 110 | fs.writeFileSync($scope.configInfo.wcmDesignsPath + '/' + library.title + '.json', JSON.stringify(library, null, ' ')); 111 | if($parent.$parent.loadingNewLibraries == 0){ 112 | $parent.$apply($parent.reload()); 113 | $parent.$parent.$apply(function(){$scope.status = 'Pulling Library ' + library.title + ' complete';}); 114 | } 115 | debugLogger.log("Success adding " + library.title); 116 | }, function(err) { 117 | debugLogger.error(err); 118 | $parent.$parent.loadingNewLibraries--; 119 | window.alert('Error Pulling Library ' + library.title + ' ' + err); 120 | $parent.$apply(); 121 | debugLogger.log("Error adding " + library.title); 122 | }); 123 | }; 124 | 125 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/spConfigController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('spConfigController', ['$scope', function($scope) { 11 | 12 | $scope.save = function(cb) { 13 | var id = $scope.$parent.configApp.folder; 14 | $scope.$parent.updateSpConfig(id, cb); 15 | 16 | var config = {prePushCommands: {}}; 17 | config.prePushCommands[id] = $scope.$parent.configApp.buildCommand; 18 | settings.setSettings(config); 19 | }; 20 | 21 | $scope.saveAndPush = function() { 22 | var id = $scope.$parent.configApp.folder; 23 | $scope.save(function() { 24 | $scope.$parent.push(id); 25 | }); 26 | }; 27 | 28 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/syncErrorController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('SyncErrorController', ['$scope', function($scope) { 11 | $scope.theme = {}; 12 | 13 | $scope.modalStatus = ""; // "conflict_recognized" | "error" 14 | 15 | // for handling sync conflicts 16 | $scope.localFileContents = ""; 17 | $scope.remoteFileContents = ""; 18 | $scope.diffs = []; 19 | 20 | // for handling general sync errors 21 | $scope.substatus = {}; 22 | $scope.error = {}; // substatus.error; 23 | 24 | 25 | $scope.$on("dxsyncErrorModal", function(e, theme) { 26 | $scope.substatus = theme.dxsync.errorStatus; 27 | $scope.modalStatus = 'error'; 28 | $scope.theme = theme; 29 | $scope.error = theme.dxsync.errorStatus.error; 30 | }); 31 | 32 | $scope.updateThemeSettings = function(property, value) { 33 | fs.readFile(dashConfig.getConfigInfo().dxThemePath + "/" + $scope.theme.folder + "/.settings", 34 | function(err, data) { 35 | if (err) { 36 | console.error(err); 37 | return; 38 | } 39 | var settings = JSON.parse(data.toString()); 40 | settings[property] = value; 41 | $scope.theme.settings = $scope.theme.settings || {}; 42 | $scope.theme.settings[property] = value; 43 | 44 | settings = JSON.stringify(settings, null, " "); 45 | $scope.$apply(); 46 | fs.writeFile(dashConfig.getConfigInfo().dxThemePath+ "/" + $scope.theme.folder + "/.settings", settings); 47 | }); 48 | }; 49 | 50 | 51 | /* CONFLICT RESOLUTION */ 52 | 53 | $scope.$on("loadSyncConflictModal", function(e, theme) { 54 | $scope.theme = theme; 55 | $scope.modalStatus = 'conflict_recognized'; 56 | 57 | for (var i in theme.conflicts) { 58 | if (theme.conflicts[i].local.match(/\.conflict$/)) { 59 | continue; 60 | } 61 | 62 | fs.readFile(theme.conflicts[i].local, function(err, localFileContents) { 63 | if (err) { 64 | console.error(err); 65 | } else { 66 | fs.readFile(theme.conflicts[i].remote, function(err, remoteFileContents) { 67 | if (err) { 68 | console.error(err); 69 | } else { 70 | diff = diff || require("diff"); 71 | 72 | theme.conflicts[i].diff = 73 | diff.diffLines(remoteFileContents.toString(), localFileContents.toString()); 74 | $scope.$apply(); 75 | } 76 | }) 77 | }; 78 | }) 79 | } 80 | }); 81 | 82 | 83 | $scope.resolveWithRemote = function(id) { 84 | $scope.theme.eventEmitter.emit("conflict_resolve", { 85 | id: id, 86 | resolveWith: $scope.theme.conflicts[id].remote, 87 | action: "upload" 88 | }); 89 | delete $scope.theme.conflicts[id]; 90 | $scope.theme.conflictRecognized = $scope.theme.conflicts.length; 91 | $scope.$apply(); 92 | }; 93 | 94 | $scope.resolveWithLocal = function(id) { 95 | $scope.theme.eventEmitter.emit("conflict_resolve", { 96 | id: id, 97 | resolveWith: $scope.theme.conflicts[id].local, 98 | action: "upload" 99 | }); 100 | delete $scope.theme.conflicts[id]; 101 | $scope.theme.conflictRecognized = $scope.theme.conflicts.length; 102 | $scope.$apply(); 103 | } 104 | 105 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/themeModulesController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('ThemeModulesController', ['$scope', function($scope) { 11 | // NOTE: modules are loaded in themesController.js 12 | 13 | $scope.addingNewModule = false; 14 | $scope.newModuleIsPredefined = false; 15 | $scope.moduleFilter = ""; 16 | 17 | $scope.finishAddingNewModule = function() { 18 | $scope.addingNewModule = false; 19 | $scope.$parent.loadModules($scope.$parent.modules.theme); 20 | }; 21 | 22 | }]); 23 | -------------------------------------------------------------------------------- /digexp-dashboard/js/controllers/wcmErrorController.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardControllers.controller('WcmErrorController', ['$scope', function($scope) { 11 | var $parent = $scope.$parent; 12 | $scope.library = {}; 13 | 14 | $scope.modalStatus = ""; // "conflict_recognized" | "error" 15 | 16 | // for handling general sync errors 17 | $scope.error = {}; // substatus.error; 18 | 19 | $scope.$on("wcmDesignErrorModal", function(e, library) { 20 | $scope.modalStatus = 'error'; 21 | $scope.library = library; 22 | var err = library.err; 23 | if(err.code == undefined) 24 | try{ 25 | err = JSON.parse(err.message); 26 | }catch(e){ 27 | err = {'responseText': err}; 28 | }; 29 | 30 | $scope.error = err; 31 | }); 32 | 33 | }]); -------------------------------------------------------------------------------- /digexp-dashboard/js/dashConfig.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var dashConfig = (function(){ 11 | var configInfo = ""; 12 | 13 | // Copy b to a 14 | var copyObj = function(a, b) { 15 | for (var key in b) { 16 | if (typeof b[key] == "object" && b[key].constructor !== Array) { 17 | a[key] = a[key] || {}; 18 | copyObj(a[key], b[key]); 19 | } else { 20 | a[key] = b[key]; 21 | } 22 | } 23 | }; 24 | 25 | return { 26 | clearConfig: function() {configInfo = "";}, 27 | getConfigInfo: function (){ 28 | // Read base config first, then get any overrides from user-settings.json 29 | if(configInfo == ""){ 30 | var fs = require('fs'); 31 | var data = fs.readFileSync('./dashboard-config.json', 'utf8'); 32 | configInfo = JSON.parse(data); 33 | if(fs.existsSync(utils.getUserSettingsName())){ 34 | var data = fs.readFileSync(utils.getUserSettingsName(), 'utf8'); 35 | var userConfig = JSON.parse(data); 36 | // Copy settings 37 | userConfig.servers.forEach(function(server){ 38 | if(server.password) 39 | var nPwd = decrypt( server.password ); 40 | if(nPwd.length != 0) 41 | server.password = nPwd; 42 | }); 43 | copyObj(configInfo, userConfig); 44 | } 45 | } 46 | return configInfo; 47 | }, 48 | setConfigInfo: function(newConfig) { 49 | configInfo = configInfo || getConfigInfo(); 50 | 51 | if(fs.existsSync("./dashboard-config.json")) { 52 | copyObj(configInfo, newConfig); 53 | configInfo.servers.forEach(function(server){ 54 | if(server.password) 55 | server.password = encrypt( server.password ); 56 | }); 57 | fs.writeFileSync(utils.getUserSettingsName(), JSON.stringify(configInfo, null, ' ')); 58 | configInfo.servers.forEach(function(server){ 59 | if(server.password) 60 | server.password = decrypt( server.password ); 61 | }); 62 | }; 63 | } 64 | ,getServerInfo: function(name){ 65 | if(configInfo == "") 66 | configInfo = this.getConfigInfo(); 67 | var rServerInfo = configInfo.servers[0]; 68 | if(name != undefined) 69 | configInfo.servers.forEach(function(serverInfo){ 70 | if(name == serverInfo.name) 71 | rServerInfo = serverInfo; 72 | }); 73 | return rServerInfo; 74 | } 75 | ,getServerForTool: function(tool){ 76 | if(configInfo == "") 77 | configInfo = this.getConfigInfo(); 78 | var rVal = "Dashboard"; 79 | switch(tool){ 80 | case this.tools.spApp: 81 | rVal = configInfo.spAppServer; 82 | break; 83 | case this.tools.dxTheme: 84 | var serverInfo = {}; 85 | copyObj(serverInfo, this.getServerInfo(configInfo.dxThemeServer)); 86 | var cPath = serverInfo.contenthandlerPath.split('/'); 87 | if (cPath.length > 3){ 88 | serverInfo.contenthandlerPath = '/' + cPath[1] + '/' + cPath[2]; 89 | }; 90 | return serverInfo; 91 | break; 92 | case this.tools.wcmDesigns: 93 | rVal = configInfo.wcmDesignsServer; 94 | break; 95 | } 96 | return this.getServerInfo(rVal); 97 | }, 98 | tools : {spApp: "spApp", dxTheme: "dxTheme", wcmDesigns: "wcmDesigns"} 99 | }; 100 | })(); -------------------------------------------------------------------------------- /digexp-dashboard/js/directives.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | dashboardApp.directive('dashCollapsible', function() { 11 | return { 12 | restrict: 'E', 13 | transclude: true, 14 | scope: { 15 | title: '@dashTitle', 16 | small: '@dashSmall' 17 | }, 18 | 19 | link: function(scope, elem, attrs) { 20 | scope.title = scope.title || attrs.title; 21 | scope.enabled = attrs.enable || false; 22 | 23 | scope.clickFun = function() { 24 | scope.enabled = !scope.enabled; 25 | }; 26 | }, 27 | template: // is the outer div necessary? 28 | '
' + 29 | ' ' + 32 | ' {{title}} ' + 33 | ' ' + 34 | ' ' + 35 | ' ' + 38 | ' {{title}} ' + 39 | ' ' + 40 | ' ' + 41 | '
' + 42 | '
' 43 | }; 44 | }); 45 | 46 | dashboardApp.directive('dashSubheader', function() { 47 | return { 48 | restrict: 'E', 49 | replace: true, 50 | transclude: true, 51 | template: 52 | '' + 53 | ' ' + 54 | '' 55 | }; 56 | }); 57 | 58 | dashboardApp.directive('dashLargeCollapsible', function() { 59 | return { 60 | restrict: 'E', 61 | transclude: true, 62 | scope: { 63 | title: '@dashTitle', 64 | subtitle: '@dashSubtitle' 65 | }, 66 | 67 | link: function(scope, elem, attrs) { 68 | scope.title = scope.title || attrs.title; 69 | scope.subtitle = scope.subtitle || attrs.subtitle; 70 | scope.enabled = attrs.enable || false; 71 | 72 | 73 | scope.clickFun = function() { 74 | scope.enabled = !scope.enabled; 75 | }; 76 | }, 77 | template: // is the outer div necessary? 78 | '
' + 79 | ' {{title}}' + 80 | '
'+ 81 | ' ' + 82 | ' ' + 83 | '
' + 84 | '
{{subtitle}}
' + 85 | '
' + 86 | '
' 87 | }; 88 | }); -------------------------------------------------------------------------------- /digexp-dashboard/js/imports.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | // stdlib imports 11 | var events = require("events"); 12 | var ch = require('child_process'), 13 | crypt = require("crypto"), // the name crypto is taken by nw.js 14 | http = require("http"), 15 | fs = require("fs"), 16 | path = require("path"); 17 | 18 | 19 | var notifier = require('node-notifier'); 20 | 21 | // npm imports 22 | // these are are imported here because they are small and don't take a long 23 | // time to load 24 | var async = require("async"), 25 | map = require("map-stream"), 26 | mkdirp = require("mkdirp"), 27 | Vinyl = require("vinyl"); 28 | 29 | 30 | var open = require('open'); 31 | 32 | 33 | // These are loaded later on so that the DOM can start rendering. 34 | var bower, 35 | diff, 36 | dxsync, 37 | request, 38 | AdmZip, 39 | splint, 40 | vfs, 41 | spAppServer; -------------------------------------------------------------------------------- /digexp-dashboard/js/nav-bar.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | 'use strict'; 11 | 12 | angular.module('dashboardApp.navBar', []) 13 | .directive('navBar', function () { 14 | return { 15 | restrict: 'E', 16 | templateUrl: 'partials/nav-bar.html', 17 | controller: 'RouteCtrl' 18 | }; 19 | }) 20 | .controller('RouteCtrl', ['$scope', '$route', '$location', function ($scope, $route, $location) { 21 | $scope.$on("$routeChangeSuccess", function (event, current, previous) { 22 | $scope.controller = $route.current.controller; 23 | }); 24 | }]); 25 | -------------------------------------------------------------------------------- /digexp-dashboard/js/settings.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var settings = (function() { 11 | return { 12 | update : function() { 13 | var configInfo = dashConfig.getConfigInfo(); 14 | configInfo.spAppPath = document.querySelector("#appPath").value; 15 | configInfo.dxThemePath = document.querySelector("#themePath").value; 16 | configInfo.wcmDesignsPath = document.querySelector("#wcmPath").value; 17 | var aServer = document.querySelector("#activeServer"); 18 | var nLength = aServer.length; 19 | 20 | configInfo.servers = []; 21 | for(var count = 0; count < nLength; count++){ 22 | configInfo.servers.push({}); 23 | configInfo.servers[count].name = (document.querySelector("#serverName"+ count) || {}).value; 24 | configInfo.servers[count].userName = (document.querySelector("#userName"+ count) || {}).value; 25 | configInfo.servers[count].password = encrypt((document.querySelector("#password"+ count) || {}).value); 26 | configInfo.servers[count].host = (document.querySelector("#host"+count) || {}).value; 27 | configInfo.servers[count].port = (document.querySelector("#port"+count) || {}).value; 28 | configInfo.servers[count].secure = (document.querySelector("#secure"+count) || {}).checked; 29 | configInfo.servers[count].contenthandlerPath = (document.querySelector("#contenthandlerPath"+count) || {}).value; 30 | } 31 | var serverIndex = aServer.value; 32 | try { 33 | configInfo.spAppServer = configInfo.dxThemeServer = configInfo.wcmDesignsServer = document.querySelector("#serverName" + serverIndex).value; 34 | } catch (e) {} 35 | 36 | // update user-settings.json 37 | fs.writeFileSync(utils.getUserSettingsName(), JSON.stringify(configInfo, null, 4)); 38 | dashConfig.clearConfig(); 39 | }, 40 | setSettings: function(newSettings) { 41 | var configInfo = dashConfig.getConfigInfo(); 42 | 43 | fs.exists(utils.getUserSettingsName(), function (exists) { 44 | if (exists) { 45 | utils.copyProperties(newSettings, configInfo); 46 | fs.writeFile(utils.getUserSettingsName(), JSON.stringify(configInfo, null, ' ')); 47 | } 48 | }); 49 | } 50 | }; 51 | })(); -------------------------------------------------------------------------------- /digexp-dashboard/js/spApp.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | // Persistently stores the apps for when the route is changed 11 | var spApp = (function() { 12 | var that = {}; 13 | 14 | that.apps = {}; 15 | 16 | return that; 17 | })(); 18 | 19 | -------------------------------------------------------------------------------- /digexp-dashboard/js/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var tracer = require("tracer"), 11 | algorithm = "aes-256-ctr", 12 | password = "U6Jv]H[tf;mxE}6t*PQz?j474A7T@Vx%gcVJA#2cr2GNh96ve+", 13 | debugEnvironmentVar = process.env.DIGEXP_DEBUG || '', 14 | debugNames = debugEnvironmentVar.toUpperCase().split(','), 15 | debugFunctions = {}; 16 | if(debugEnvironmentVar.length != 0) 17 | require('nw.gui').Window.get().showDevTools(); 18 | 19 | function debugLogger(moduleName) { 20 | moduleName = moduleName.toUpperCase(); 21 | if (!debugFunctions[moduleName]) { 22 | var logLevel = 'error'; 23 | if (debugNames.indexOf(moduleName) > -1 || debugNames.indexOf('*') > -1) { 24 | logLevel = 'log'; 25 | } 26 | else 27 | if(debugEnvironmentVar.length != 0) 28 | logLevel = debugEnvironmentVar; 29 | debugFunctions[moduleName] = tracer.console({ 30 | level: logLevel, 31 | // for details on format, see: https://www.npmjs.com/package/tracer 32 | format: moduleName + ' ' + '{{timestamp}} {{file}}:{{line}} {{message}}', 33 | }); 34 | } 35 | return debugFunctions[moduleName]; 36 | }; 37 | 38 | function encrypt( text ) { 39 | var crypto = require('crypto'); 40 | var cipher = crypto.createCipher( algorithm, password ); 41 | var crypted = cipher.update( text, "utf8", "hex" ); 42 | crypted += cipher.final( "hex" ); 43 | return crypted; 44 | } 45 | 46 | function decrypt( text ) { 47 | var crypto = require('crypto'); 48 | var decipher = crypto.createDecipher( algorithm, password ); 49 | var dec = decipher.update( text, "hex", "utf8" ); 50 | dec += decipher.final( "utf8" ); 51 | return dec; 52 | } 53 | 54 | var getModified = function(dirName, dateString, ignore, callback){ 55 | // takes the name of the directory you want to find the modified and a string for a date that is the toLocaleString of a date object 56 | // 57 | var dirs = []; 58 | var Path = require('path'); 59 | var cDate = undefined; 60 | var re = new RegExp('/', 'g'); 61 | ignore = ignore.replace(re, Path.sep); 62 | 63 | var ignores = ignore.split(';'); 64 | if(dateString != undefined) 65 | cDate = new Date(dateString); 66 | var finder = require('findit')(dirName); 67 | 68 | finder.on('directory', function (dir, stat, stop) { 69 | // stop as soon as we find one difference 70 | if(dirs.length != 0) 71 | return stop(); 72 | var dirname = Path.dirname(dir); 73 | // ignore the folders ToDo done this a better way 74 | ignores.forEach(function(ignore){ 75 | if(ignore.indexOf('/') > -1 && dirname.indexOf(ignore) > -1) 76 | return stop(); 77 | }); 78 | }); 79 | 80 | 81 | finder.on('file', function (file, stat) { 82 | // stop as soon as we find one difference 83 | var ignored = false; 84 | var base = Path.basename(file); 85 | // ignore the folders ToDo done this a better way 86 | ignores.forEach(function(ignore){ 87 | if (ignore.indexOf('/') == -1 && base.indexOf(ignore) > -1) 88 | ignored = true; 89 | }); 90 | // no date so go back to the start 91 | if(dateString == "") 92 | cDate = new Date('01/01/1970'); 93 | if(!ignored && (stat.mtime > cDate || stat.birthtime > cDate)){ 94 | dirs.push(dirName); 95 | stop(); 96 | }; 97 | }); 98 | 99 | finder.on('end',function (){ 100 | callback(dirs); 101 | }); 102 | }; 103 | 104 | var utils = utils || {}; 105 | 106 | var userHome = getUserHome(); 107 | var settingsFileName; 108 | // Copy the properties of a onto b 109 | utils.copyProperties = function(a, b) { 110 | for (var key in a) { 111 | if (typeof a[key] == "object" && a[key].constructor !== Array) { 112 | b[key] = b[key] || {}; 113 | utils.copyProperties(a[key], b[key]); 114 | } else { 115 | b[key] = a[key]; 116 | } 117 | } 118 | }; 119 | 120 | // get the user settings file name 121 | utils.getUserSettingsName = function(){ 122 | if(settingsFileName) 123 | return settingsFileName; 124 | var Path = require('path'); 125 | if(userHome.length != 0){ 126 | // make sure the path ends in a path separator 127 | if(userHome.lastIndexOf(Path.sep) != userHome.length -1) 128 | userHome += Path.sep; 129 | } 130 | else 131 | userHome = '.' + Path.sep; 132 | settingsFileName = userHome + 'user-settings.json'; 133 | return settingsFileName; 134 | }; 135 | 136 | function getUserHome() { 137 | return process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']; 138 | } 139 | 140 | 141 | utils.debugLogger = debugLogger; 142 | utils.encrypt = encrypt; 143 | utils.decrypt = decrypt; 144 | 145 | -------------------------------------------------------------------------------- /digexp-dashboard/js/wcmDesign.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var path = require("path"), 11 | fs = require("fs"); 12 | var wcmHelper = require("digexp-wcm-design"); 13 | var tmpInfo = dashConfig.getConfigInfo(); 14 | var wcmDesignsFolder = tmpInfo.wcmDesignsPath; 15 | var wcmDesignMap = {}; 16 | var wcmLibraries ={}; 17 | var server = dashConfig.getServerForTool(dashConfig.tools.wcmDesigns); 18 | var parseDate = function(dateStr) { 19 | var result = new Date(dateStr).toLocaleString(); 20 | return result !== "Invalid Date" ? result : ""; 21 | }; 22 | var wcmDesign = (function() { 23 | return { 24 | wcmDesigns: wcmDesignMap, 25 | init: function( host, port, contenthandlerPath , userName, password, secure, designsFolder){ 26 | wcmHelper.init(host, port, contenthandlerPath , userName, password, secure, designsFolder); 27 | }, 28 | getWcmDesigns:function () { 29 | /** 30 | * Loads the list objects for each library into memory. 31 | */ 32 | var errLibs= {}; 33 | console.log(wcmDesignsFolder); 34 | 35 | Object.keys(wcmDesignMap).forEach(function(title){ 36 | var wcmDesign = wcmDesignMap[title]; 37 | if(wcmDesign.err != undefined && wcmDesign.err != null) 38 | errLibs[title]=wcmDesign.err; 39 | }); 40 | var configInfo = dashConfig.getConfigInfo(); 41 | 42 | if (!configInfo.wcmDesignsPath) { 43 | debugLogger.log("wcmDesignsFolder has not been set"); 44 | for (var key in wcmDesignMap) { 45 | delete wcmDesignMap[key]; 46 | } 47 | } 48 | if (wcmDesignsFolder !== configInfo.wcmDesignsPath) { 49 | // reset the designs if a different directory is used 50 | // delete is used to clear the object but maintain the reference 51 | for (var key in wcmDesignMap) { 52 | delete wcmDesignMap[key]; 53 | } 54 | } 55 | wcmDesignsFolder = configInfo.wcmDesignsPath; 56 | 57 | var files = fs.readdirSync(wcmDesignsFolder); 58 | 59 | files.forEach(function(file) { 60 | var fName = wcmDesignsFolder + '/' + file; 61 | var stats = fs.lstatSync(fName); 62 | 63 | if (!stats.isDirectory()) { 64 | var foldName = fName.slice(0, fName.length -5); 65 | if(fs.existsSync(foldName)){ 66 | try{ 67 | var data = fs.readFileSync(fName, 'utf8'); 68 | var library = JSON.parse(data); 69 | var libSettings = wcmHelper.getSettings(library.title); 70 | var wcmDesign = { 71 | title: library.title, 72 | summary: library.summary, 73 | datePushed: parseDate(libSettings.datePushed), 74 | serverPushed: libSettings.serverPushed, 75 | datePulled: parseDate(libSettings.datePulled), 76 | serverPulled: libSettings.serverPulled, 77 | dateUpdated: parseDate(libSettings.updated), 78 | config: library 79 | }; 80 | 81 | if (!wcmDesign.dateUpdated) { 82 | if (wcmDesign.datePulled) { 83 | wcmDesign.dateUpdated = wcmDesign.datePulled; 84 | } 85 | if (wcmDesign.datePushed && (!wcmDesign.datePushed || wcmDesign.datePushed > wcmDesign.datePulled)) { 86 | wcmDesign.dateUpdated = wcmDesign.datePushed; 87 | } 88 | } 89 | Object.keys(errLibs).forEach(function(title){ 90 | if(title == library.title){ 91 | wcmDesign.error = true; 92 | try{ 93 | err = new Error(errLibs[title].message); 94 | }catch(e){ 95 | err = {'responseText': err}; 96 | }; 97 | wcmDesign.err = err; 98 | } 99 | }); 100 | wcmDesignMap[library.title]= wcmDesign; 101 | }catch (e){debugLogger.log('error getting::' + fName + ' error::' +e);} 102 | 103 | } 104 | } 105 | }); 106 | return wcmDesignMap; 107 | }, 108 | pull: function(library){ 109 | //this.getWcmDesigns(); 110 | var options = {includeMeta: false, filterComponentId: true}; 111 | return wcmHelper.pullLibrary(library.title, options); 112 | }, 113 | push: function(library, force){ 114 | return wcmHelper.pushLibrary(library.title, force); 115 | } 116 | }; 117 | })(); 118 | -------------------------------------------------------------------------------- /digexp-dashboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digexp-dashboard", 3 | "description": "Web Developer Dashboard for IBM Digital Experience", 4 | "version": "0.1.8", 5 | "main": "dashboard_index.html", 6 | "bin": { 7 | "dxdashboard": "bin/dxdashboard" 8 | }, 9 | "window": { 10 | "show": true, 11 | "toolbar": false, 12 | "frame": true, 13 | "position": "center", 14 | "title": "Web Developer Dashboard for IBM Digital Experience v0.1.7", 15 | "width": 990, 16 | "height": 729, 17 | "min_width": 960, 18 | "min_height": 220, 19 | "single-instance": false 20 | }, 21 | "dependencies": { 22 | "ScriptAppServer": "file:../sp-server.tar.gz", 23 | "adm-zip": "^0.4.7", 24 | "anymatch": "^1.3.0", 25 | "async": "^1.3.0", 26 | "chokidar": "^1.0.3", 27 | "diff": "^1.4.0", 28 | "dxsync": "https://github.com/OpenNTF/WebDevToolkitForDx/blob/master/TempPatch/dxsync-1.0.2.tar.gz?raw=true", 29 | "digexp-wcm-design": "file:../wcm-design.tar.gz", 30 | "findit": "", 31 | "map-stream": "0.0.6", 32 | "mkdirp": "^0.5.1", 33 | "node-notifier": "^4.2.3", 34 | "open": "^0.0.5", 35 | "request": "^2.58.0", 36 | "splint": "https://github.com/OpenNTF/Script-Portlet-Node-Samples/raw/master/splint.tgz", 37 | "tracer": "0.8.0", 38 | "vinyl": "^0.5.0", 39 | "vinyl-fs": "^1.0.0" 40 | }, 41 | "config": { 42 | "unsafe-perm": true, 43 | "no-optional": true 44 | }, 45 | "scripts": { 46 | "preinstall": "node preinstall.js", 47 | "postinstall": "node postinstall.js" 48 | }, 49 | "engines": { 50 | "node": ">=0.12" 51 | }, 52 | "engine-strict": true 53 | } 54 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/appDetailsView.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
Application NameFoo
File Locationfoo folder
Descriptionfoo description
18 |
-------------------------------------------------------------------------------- /digexp-dashboard/partials/listWcmDesignsView.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

WCM Design Libraries 4 | 6 |

7 |

8 | {{configInfo.wcmDesignsPath}}

9 |
10 |
{{status}}
11 |
12 | Error: 13 | Path {{configInfo.wcmDesignsPath}} not found. 14 |
15 |

Please set a WCM Design Libraries folder in settings

16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 32 |
33 |
34 |
35 |
36 |
37 | No WCM libraries found in {{configInfo.wcmDesignsPath}}. 38 |
39 |
40 |
41 |
42 |
43 |

{{wcmDesign.title}} 44 | 47 |

48 |
{{status}}
49 |
{{wcmDesign.summary}}
50 |
51 | {{wcmDesign.dateUpdated}} 52 |
53 |
54 |
55 |
56 | 62 | 63 |
64 | Pushed: {{wcmDesign.datePushed}}
65 |
66 | Pulled: {{wcmDesign.datePulled}}
67 |
68 |
69 | 72 | 75 | 78 | 97 | 101 |
102 |
103 |
104 |
105 |
106 | 107 | 111 | 112 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/cdnSuggestionsArea.html: -------------------------------------------------------------------------------- 1 |
4 | 5 |
6 |
9 | {{suggestion.name}} {{suggestion.version}}
10 |
11 |
12 |
13 | 15 | 16 |
19 | {{asset.version}} 20 |
21 |
22 |
-------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/cloneThemeModal.html: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/listThemesModal.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/listWcmDesignsModal.html: -------------------------------------------------------------------------------- 1 | 70 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/syncErrorModal.html: -------------------------------------------------------------------------------- 1 | 94 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/modals/wcmErrorModal.html: -------------------------------------------------------------------------------- 1 | 44 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/nav-bar.html: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /digexp-dashboard/partials/settingsView.html: -------------------------------------------------------------------------------- 1 |
2 |

Settings

3 |

4 | Server configuration and folder locations can be managed here. 5 | The folders specified here will be used as the parent folders for each type. Under the parent folder there will be child folders for each application/theme/library. 6 |

7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 28 | 29 |
11 | 12 | 13 |
18 | 19 | 20 |
25 | 26 | 27 |
30 | 31 |

Servers

32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 56 | 61 | 66 | 70 | 74 | 77 | 81 | 85 | 86 |
NameUser NamePasswordHostPortContent HandlerSecure
48 | 50 | 52 | 55 | 57 | 60 | 62 | 65 | 67 | 69 | 71 | 73 | 75 | 76 | 78 | 80 | 82 | 84 |
87 | 88 |
89 | 94 | 95 | 96 | Please enter the required fields 97 |
98 | 99 |
100 | 101 | 125 | -------------------------------------------------------------------------------- /digexp-dashboard/postinstall.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var fs = require("fs"); 11 | var ch = require("child_process"); 12 | var path = require("path"); 13 | var async = require("async"); 14 | var rm_rf = function(path, cb) { 15 | fs.stat(path, function(err, stats) { 16 | if (err) { 17 | cb && cb(err); 18 | } else if (stats.isDirectory()) { 19 | fs.readdir(path, function(err, files) { 20 | if (err) { 21 | cb && cb(err); 22 | } else { 23 | async.parallel(files.map(function(file) { 24 | // delete each file 25 | return function(cb) { 26 | rm_rf(path + "/" + file, cb); 27 | }; 28 | }), function() { 29 | // then delete the directory 30 | fs.rmdir(path, function(err) { 31 | cb && cb(err); 32 | }); 33 | }); 34 | } 35 | }); 36 | } else { 37 | fs.unlink(path, function(err) { 38 | cb && cb(err); 39 | }); 40 | } 41 | }); 42 | }; 43 | console.log("Installing dxsync:"); 44 | var cwd = process.cwd(); 45 | var command = "npm install --no-optional --no-bin-links --prefix " + cwd + " https://github.com/OpenNTF/WebDevToolkitForDx/blob/master/TempPatch/dxsync-1.0.2.tar.gz?raw=true"; 46 | if (process.platform == "win32") { 47 | command = "https://github.com/OpenNTF/WebDevToolkitForDx/blob/master/TempPatch/dxsync-1.0.2.tar.gz?raw=true"; 48 | }; 49 | var cleanup = function() { 50 | rm_rf("node_modules/dxsync/precompiled_modules/"); 51 | rm_rf("node_modules/dxsync/precompiled_modules.zip"); 52 | }; 53 | var cleanupWindows = function(cb) { 54 | ch.exec("npm root -g", { }, function(err, root) { 55 | root = root || process.env._; 56 | if (root && fs.existsSync(root + "\\dxsync\\package.json")) { 57 | ch.exec('xcopy "' + root + '\\dxsync" "' + process.cwd() + '\\node_modules\\dxsync" /e /y', function() { 58 | cb && cb(); 59 | }); 60 | } else { 61 | cb && cb(); 62 | } 63 | }); 64 | }; 65 | var cleanupUnix = function(cb) { 66 | if (fs.existsSync("lib/node_modules/dxsync/package.json")) { 67 | ch.exec("cp -r lib/node_modules/dxsync/ node_modules/dxsync/", function() { 68 | rm_rf("lib/node_modules/dxsync"); 69 | // ./lib/ shouldn't exist in this version of npm 70 | cb && cb(); 71 | }); 72 | }; 73 | }; 74 | cleanup(); 75 | /*ch.exec(command, { cwd: cwd }, 76 | function(err, stdout, stderr) { 77 | if (stdout) { 78 | console.log(stdout); 79 | } 80 | if (stderr) { 81 | console.error(stderr); 82 | } 83 | if (err) { 84 | console.error("Error installing dxsync: " + err.message); 85 | } else if (process.platform == "win32") { 86 | cleanupWindows(cleanup); 87 | } else { 88 | cleanupUnix(cleanup); 89 | } 90 | setTimeout(function() { 91 | console.log("Done!") 92 | }, 500); 93 | });*/ 94 | // check if user-settings has been saved temporarily 95 | // (for saving settings when re-installing the dashboard globally) 96 | ch.exec("npm root -g", { }, function(err, root) { 97 | root = root || process.env._; 98 | if (root) { 99 | root = root.replace(/\n|\r/g, ""); 100 | fs.readFile(path.resolve(root, ".digexp-dashboard-user-settings.json"), function(err, contents) { 101 | if (!err) { 102 | fs.writeFile(path.resolve(root, "digexp-dashboard/user-settings.json"), contents); 103 | fs.unlink(path.resolve(root, ".digexp-dashboard-user-settings.json")) 104 | } 105 | }); 106 | } 107 | }); -------------------------------------------------------------------------------- /digexp-dashboard/preinstall.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var path = require("path"); 11 | var fs = require("fs"); 12 | var ch = require("child_process"); 13 | 14 | ch.exec("npm root -g", function(err, root) { 15 | root = root || process.env._; 16 | console.log(root); 17 | if (root) { 18 | root = root.replace(/\n|\r/g, ""); 19 | fs.readFile(path.resolve(root, "digexp-dashboard/user-settings.json"), 20 | function(err, contents) { 21 | if (!err) { 22 | fs.writeFile(path.resolve(root, ".digexp-dashboard-user-settings.json"), 23 | contents, function() { 24 | console.log("PREINSTALL DONE!"); 25 | }); 26 | } 27 | }); 28 | } 29 | }); 30 | 31 | 32 | -------------------------------------------------------------------------------- /digexp-dashboard/spconfig/configbuild.json: -------------------------------------------------------------------------------- 1 | { 2 | "mainPortletClass": "__SPNS__sp-wrapper", 3 | "cwd": "./", 4 | 5 | "fix": true, 6 | "fixes": { 7 | "css-selectors": true, 8 | "css-positions": true, 9 | "html-jquery": true 10 | }, 11 | 12 | "raw": false, 13 | "logFile": "", 14 | 15 | "silent": true, 16 | "verbose": true, 17 | 18 | "src": ["./**", "!**/node_modules/**", "!node_modules", "!**/sp-build/**", "!.", "!sp-build"], 19 | "dest": "release" 20 | } -------------------------------------------------------------------------------- /digexp-dashboard/spconfig/configlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "fix": false, 3 | 4 | "checks" : { 5 | "css-selectors": true, 6 | "css-widths": true, 7 | "css-positions": true, 8 | "css-fonts": true, 9 | "html-jquery": true, 10 | "js-selectors": true, 11 | "js-urls": true 12 | }, 13 | 14 | "raw": false, 15 | "silent": true, 16 | "verbose": true, 17 | 18 | "src": ["./**", "!**/node_modules/**", "!node_modules", "!**/sp-build/**", "!.", "!sp-build"], 19 | "dest": "sp-build" 20 | } -------------------------------------------------------------------------------- /digexp-dashboard/splogs/readme: -------------------------------------------------------------------------------- 1 | Use this as a folder for log info for your apps 2 | -------------------------------------------------------------------------------- /digexp-dashboard/tag-replacements.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user[wp.themeConfig['user.displaynameattribute']]}\"]", 3 | "tagMockValue": "John Doe" 4 | }, { 5 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.cn}\"]", 6 | "tagMockValue": "jdoe" 7 | }, { 8 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.sn}\"]", 9 | "tagMockValue": "doe" 10 | }, { 11 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.uid}\"]", 12 | "tagMockValue": "jdoe" 13 | }, { 14 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.preferredLanguage}\"]", 15 | "tagMockValue": "en" 16 | }, { 17 | "tagName": "[Property context=\"current\" type=\"auto\" format=\"cn\" field=\"authors\"]", 18 | "tagMockValue": "jdoe" 19 | }, { 20 | "tagName": "[Property context=\"current\" type=\"auto\" field=\"title\"]", 21 | "tagMockValue": "Dummy Title" 22 | }, { 23 | "tagName": "[Property context=\"current\" type=\"parent\" field=\"title\"]", 24 | "tagMockValue": "Dummy Parent Title" 25 | }, { 26 | "tagName": "[Plugin:Portlet key=\"namespace\"]", 27 | "tagMockValue": "ns123" 28 | }, { 29 | "tagName": "[Plugin:Locale]", 30 | "tagMockValue": "en_US" 31 | }, { 32 | "tagName": "[Plugin:PageMode pageMode=\"EDIT\"]", 33 | "tagMockValue": "" 34 | }, { 35 | "tagName": "[Plugin:ifDevice class=\"\"]", 36 | "tagMockValue": "" 37 | }, { 38 | "tagName": "[Plugin:ifDeviceclass=\"smartphone\"]", 39 | "tagMockValue": "" 40 | }, { 41 | "tagName": "[Plugin:ifDevice class=\"tablet\"]", 42 | "tagMockValue": "" 43 | }, { 44 | "tagName": "[Plugin:ifDevice class=\"iOS\"]", 45 | "tagMockValue": "" 46 | }, { 47 | "tagName": "[/Plugin:PageMode]", 48 | "tagMockValue": "" 49 | }, { 50 | "tagName": "[/Plugin:ifDevice]", 51 | "tagMockValue": "" 52 | }] -------------------------------------------------------------------------------- /digexp-sp-server/.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | ################# 32 | ## node_modules 33 | ################# 34 | 35 | node_modules 36 | 37 | ################# 38 | ## Visual Studio 39 | ################# 40 | 41 | ## Ignore Visual Studio temporary files, build results, and 42 | ## files generated by popular Visual Studio add-ons. 43 | 44 | # User-specific files 45 | *.suo 46 | *.user 47 | *.sln.docstates 48 | 49 | # Build results 50 | 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | x64/ 54 | build/ 55 | [Bb]in/ 56 | [Oo]bj/ 57 | 58 | # MSTest test Results 59 | [Tt]est[Rr]esult*/ 60 | [Bb]uild[Ll]og.* 61 | 62 | *_i.c 63 | *_p.c 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.log 84 | *.scc 85 | 86 | # Visual C++ cache files 87 | ipch/ 88 | *.aps 89 | *.ncb 90 | *.opensdf 91 | *.sdf 92 | *.cachefile 93 | 94 | # Visual Studio profiler 95 | *.psess 96 | *.vsp 97 | *.vspx 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | *.ncrunch* 114 | .*crunch*.local.xml 115 | 116 | # Installshield output folder 117 | [Ee]xpress/ 118 | 119 | # DocProject is a documentation generator add-in 120 | DocProject/buildhelp/ 121 | DocProject/Help/*.HxT 122 | DocProject/Help/*.HxC 123 | DocProject/Help/*.hhc 124 | DocProject/Help/*.hhk 125 | DocProject/Help/*.hhp 126 | DocProject/Help/Html2 127 | DocProject/Help/html 128 | 129 | # Click-Once directory 130 | publish/ 131 | 132 | # Publish Web Output 133 | *.Publish.xml 134 | *.pubxml 135 | *.publishproj 136 | 137 | # NuGet Packages Directory 138 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 139 | #packages/ 140 | 141 | # Windows Azure Build Output 142 | csx 143 | *.build.csdef 144 | 145 | # Windows Store app package directory 146 | AppPackages/ 147 | 148 | # Others 149 | sql/ 150 | *.Cache 151 | ClientBin/ 152 | [Ss]tyle[Cc]op.* 153 | ~$* 154 | *~ 155 | *.dbmdl 156 | *.[Pp]ublish.xml 157 | *.pfx 158 | *.publishsettings 159 | 160 | # RIA/Silverlight projects 161 | Generated_Code/ 162 | 163 | # Backup & report files from converting an old project file to a newer 164 | # Visual Studio version. Backup files are not needed, because we have git ;-) 165 | _UpgradeReport_Files/ 166 | Backup*/ 167 | UpgradeLog*.XML 168 | UpgradeLog*.htm 169 | 170 | # SQL Server files 171 | App_Data/*.mdf 172 | App_Data/*.ldf 173 | 174 | ############# 175 | ## Windows detritus 176 | ############# 177 | 178 | # Windows image file caches 179 | Thumbs.db 180 | ehthumbs.db 181 | 182 | # Folder config file 183 | Desktop.ini 184 | 185 | # Recycle Bin used on file shares 186 | $RECYCLE.BIN/ 187 | 188 | # Mac crap 189 | .DS_Store 190 | 191 | 192 | ############# 193 | ## Python 194 | ############# 195 | 196 | *.py[cod] 197 | 198 | # Packages 199 | *.egg 200 | *.egg-info 201 | dist/ 202 | build/ 203 | eggs/ 204 | parts/ 205 | var/ 206 | sdist/ 207 | develop-eggs/ 208 | .installed.cfg 209 | 210 | # Installer logs 211 | pip-log.txt 212 | 213 | # Unit test / coverage reports 214 | .coverage 215 | .tox 216 | 217 | #Translations 218 | *.mo 219 | 220 | #Mr Developer 221 | .mr.developer.cfg 222 | -------------------------------------------------------------------------------- /digexp-sp-server/README.md: -------------------------------------------------------------------------------- 1 | # Simple test server for Script Portlet with mock implementations of WCM tags 2 | 3 | This is a simple implementation of a web server that provides mock implementations 4 | of portal-specific features. It substitutes common WCM tags with mock data and 5 | removes others. The list of tag substitutions comes from the tag-replacements.json 6 | file. In addition, the server provides support for handling ResourceURL tags for 7 | generating urls for Portal's Ajax proxy. 8 | 9 | This test server is used by the Web Developer Dashboard part of this toolkit when 10 | you click the "Run" button for a script application. It's installed automatically 11 | when you install the dashboard, so typically you don't need to use the installation 12 | described below. 13 | 14 | ## Installation 15 | To install: 16 | - You must have Node.js and npm installed. 17 | - Download this source code from Git. 18 | - From the digexp-sp-server folder, run: 19 | ``` 20 | npm install 21 | ``` 22 | 23 | ## Running from the Command Line 24 | To run the web server, specify the root of the folder you want to serve like this: 25 | ``` 26 | node script-portlet-server.js d:/samples 27 | ``` 28 | 29 | This will serve up files from that specified folder at port 3000, e.g., http://localhost:3000/index.html or http://localhost:3000/mysample/index.html 30 | 31 | ## Using the API 32 | In your package.json file, include: 33 | 34 | ``` 35 | "dependencies": { 36 | "ScriptAppServer": "file:../", 37 | } 38 | ``` 39 | 40 | Then in a javascript file, you can use: 41 | 42 | ``` 43 | var spAppServer = require('ScriptAppServer'); 44 | 45 | var spAppFolder = 'd:/samples' 46 | var port = 3000; 47 | 48 | var serverInstance = spAppServer.start(spAppFolder, port); 49 | 50 | // ... later, close the port when finished 51 | serverInstance.close(); 52 | ``` 53 | -------------------------------------------------------------------------------- /digexp-sp-server/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var express = require('express'); 11 | var request = require('request'); 12 | var path = require('path'); 13 | var fs = require('fs'); 14 | 15 | const DEFAULT_PORT = 3000; 16 | 17 | // get list of WCM tags with replacements 18 | var tagMap = require('./tag-replacements.json'); 19 | 20 | function doTagReplacement(contents) { 21 | var substr = contents; 22 | // @todo add other tag prefixes 23 | var tagPrefixes = ['Plugin', 'Property', 'If', 'URLCmpnt', 'Component']; 24 | var tagsToMatch = []; 25 | tagPrefixes.forEach(function(entry) { 26 | tagsToMatch.push('\\[' + entry); 27 | tagsToMatch.push('\\[\\/' + entry); 28 | }); 29 | var tagPattern = tagsToMatch.join('|'); 30 | var index = substr.search(tagPattern); 31 | var tagsFound = []; 32 | var endTagsFound = []; 33 | // var resultText = ''; 34 | while (index >= 0) { 35 | substr = substr.substring(index); 36 | var endIndex = findEndTag(substr); 37 | if (endIndex >= 0) { 38 | var wcmTag = substr.substring(0, endIndex + 1); 39 | if (wcmTag.indexOf('[/') == 0) { 40 | endTagsFound.push(wcmTag); 41 | } else { 42 | tagsFound.push(wcmTag); 43 | } 44 | substr = substr.substring(endIndex + 1); 45 | } 46 | index = substr.search(tagPattern); 47 | } 48 | 49 | // Now do replacement. If none found, replaces with empty string 50 | // @todo Use a more intelligent replacement - this just looks for an exact match of specific tags, 51 | 52 | var newContents = contents; 53 | for (var i = 0; i < tagsFound.length; i++) { 54 | var tag = tagsFound[i]; 55 | if (tag.match(/Plugin:ResourceURL/)) { 56 | newContents = newContents.replace(tag, getResourceURL(tag)); 57 | } else { 58 | newContents = newContents.replace(tag, getMockValue(tag, tagMap)); 59 | } 60 | } 61 | for (var i = 0; i < endTagsFound.length; i++) { 62 | var tag = endTagsFound[i]; 63 | newContents = newContents.replace(tag, getMockValue(tag, tagMap)); 64 | } 65 | return newContents; 66 | } 67 | 68 | function getMockValue(tag, tagMap) { 69 | for (var i = 0, len = tagMap.length; i < len; i++) { 70 | if (tag == tagMap[i].tagName) { 71 | return tagMap[i].tagMockValue; 72 | } 73 | } 74 | return ""; 75 | } 76 | 77 | /** 78 | * Replaces a Plugin:ResourceURL tag with the url being processed. 79 | * NOTE: this may fail for nested tags 80 | */ 81 | function getResourceURL(tag) { 82 | var url = tag.match(/url="[^"]*"/)[0] || 'url=""'; 83 | url = url.substring('url="'.length, url.length - 1); 84 | 85 | // Checks if the url has a query string but it doesn't verify correctness. 86 | var hasQueryString = url.match(/\?[\w-&=]*$/); 87 | var params = tag.match(/param="[^"]+"/g) || []; 88 | var start = 'param="'.length; 89 | params = params.map(function(param) { return param.substring(start, param.length - 1); }) 90 | .join('&'); 91 | 92 | if (params) { 93 | url += hasQueryString ? '&' : '?'; 94 | url += params; 95 | } 96 | 97 | var proxy = !tag.match(/proxy="false"/); 98 | if (proxy) { 99 | return "/wps/proxy/" + url.replace(":/", ""); 100 | } else { 101 | return url; 102 | } 103 | } 104 | 105 | function findEndTag(substr) { 106 | var inQuotes = false; 107 | for (var i = 0, len = substr.length; i < len; i++) { 108 | if (substr[i] == ']' && !inQuotes) { 109 | return i; 110 | } 111 | if (substr[i] == '"') { 112 | inQuotes = !inQuotes; 113 | } 114 | } 115 | return -1; 116 | 117 | } 118 | 119 | function unescapeCharacters(str) { 120 | return str.replace(/%(\d+)/g, function(match, dec) { 121 | return String.fromCharCode(parseInt(+dec, 16)); 122 | }); 123 | } 124 | 125 | exports.start = function start(dir, port) { 126 | port = port || DEFAULT_PORT; 127 | 128 | var app = express(); 129 | 130 | console.log('server running at port ' + port + ' using root folder ' + dir); 131 | 132 | app.get(/^\/wps\/proxy\/http/, function(req, resp) { 133 | var url = req.url.substring("/wps/proxy/".length); 134 | url = url.replace(/^https?/, function(match) { 135 | return match + ":/"; 136 | }); 137 | 138 | // Including these headers sometimes gets 404 responses 139 | delete req.headers["referer"]; 140 | delete req.headers["host"]; 141 | 142 | request.get({ 143 | url: url, 144 | headers: req.headers, 145 | rejectUnauthorized: false 146 | }).pipe(resp); 147 | }); 148 | 149 | // Special processing for HTML and JS files 150 | app.get(['/*.html', '/*.js'], function(req, res) { 151 | console.log('get ' + req.path); 152 | var filePath = unescapeCharacters(path.join(dir, req.path)); 153 | // read file contents 154 | fs.readFile(filePath, 'utf8', function(err, contents) { 155 | if (err) { 156 | res.status(500).send(err.message); 157 | } else { 158 | contents = doTagReplacement(contents.toString()); 159 | // console.log('sending: ' + contents); 160 | res.send(contents); 161 | } 162 | }); 163 | }); 164 | 165 | // All other files get served up by default handling 166 | app.use(express.static(dir)); 167 | 168 | // Listen on port 169 | return app.listen(port); 170 | }; 171 | -------------------------------------------------------------------------------- /digexp-sp-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ScriptAppServer", 3 | "version": "0.1.2", 4 | "main": "./index.js", 5 | "dependencies": { 6 | "express": ">=3.x", 7 | "request": "^2.69.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /digexp-sp-server/script-portlet-server.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var spServer = require('./index.js'); 11 | 12 | var args = process.argv.slice(2); 13 | var dir = args[0] || __dirname + '/public'; 14 | var port = args[1] || 3000; 15 | 16 | var server = spServer.start(dir, port); 17 | 18 | process.on('SIGTERM', function() { 19 | server.close(function() { 20 | process.exit(0); 21 | }); 22 | }); -------------------------------------------------------------------------------- /digexp-sp-server/tag-replacements.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user[wp.themeConfig['user.displaynameattribute']]}\"]", 3 | "tagMockValue": "John Doe" 4 | }, { 5 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.cn}\"]", 6 | "tagMockValue": "jdoe" 7 | }, { 8 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.sn}\"]", 9 | "tagMockValue": "doe" 10 | }, { 11 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.uid}\"]", 12 | "tagMockValue": "jdoe" 13 | }, { 14 | "tagName": "[Plugin:EvaluateEL value=\"${wp.user.preferredLanguage}\"]", 15 | "tagMockValue": "en" 16 | }, { 17 | "tagName": "[Property context=\"current\" type=\"auto\" format=\"cn\" field=\"authors\"]", 18 | "tagMockValue": "jdoe" 19 | }, { 20 | "tagName": "[Property context=\"current\" type=\"auto\" field=\"title\"]", 21 | "tagMockValue": "Dummy Title" 22 | }, { 23 | "tagName": "[Property context=\"current\" type=\"parent\" field=\"title\"]", 24 | "tagMockValue": "Dummy Parent Title" 25 | }, { 26 | "tagName": "[Plugin:Portlet key=\"namespace\"]", 27 | "tagMockValue": "ns123" 28 | }, { 29 | "tagName": "[Plugin:Locale]", 30 | "tagMockValue": "en_US" 31 | }, { 32 | "tagName": "[Plugin:PageMode pageMode=\"EDIT\"]", 33 | "tagMockValue": "" 34 | }, { 35 | "tagName": "[Plugin:ifDevice class=\"\"]", 36 | "tagMockValue": "" 37 | }, { 38 | "tagName": "[Plugin:ifDeviceclass=\"smartphone\"]", 39 | "tagMockValue": "" 40 | }, { 41 | "tagName": "[Plugin:ifDevice class=\"tablet\"]", 42 | "tagMockValue": "" 43 | }, { 44 | "tagName": "[Plugin:ifDevice class=\"iOS\"]", 45 | "tagMockValue": "" 46 | }, { 47 | "tagName": "[/Plugin:PageMode]", 48 | "tagMockValue": "" 49 | }, { 50 | "tagName": "[/Plugin:ifDevice]", 51 | "tagMockValue": "" 52 | }] -------------------------------------------------------------------------------- /digexp-wcm-design/.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | node_modules 3 | .project -------------------------------------------------------------------------------- /digexp-wcm-design/bin/dxwcmdesigns: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | require("../wcmdesigns.js"); -------------------------------------------------------------------------------- /digexp-wcm-design/bin/wcmHelper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* 4 | * Copyright 2015 IBM Corp. 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed 10 | * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | * CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | * specific language governing permissions and limitations under the License. 13 | */ 14 | 15 | require("../wcmHelper.js"); -------------------------------------------------------------------------------- /digexp-wcm-design/lib/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | var tracer = require("tracer"), 11 | debugEnvironmentVar = process.env.DIGEXP_DEBUG || '', 12 | debugNames = debugEnvironmentVar.toUpperCase().split(','), 13 | debugFunctions = {}, 14 | settings = {}, 15 | fs = require("fs"); 16 | 17 | var debugLogger = function(moduleName) { 18 | moduleName = moduleName.toUpperCase(); 19 | if (!debugFunctions[moduleName]) { 20 | var logLevel = 'error'; 21 | if (debugNames.indexOf(moduleName) > -1 || debugNames.indexOf('*') > -1) { 22 | logLevel = 'log'; 23 | } 24 | /* 25 | else{ 26 | if(debugEnvironmentVar.length != 0) 27 | logLevel = debugEnvironmentVar; 28 | } 29 | */ 30 | debugFunctions[moduleName] = tracer.console({ 31 | level: logLevel, 32 | // for details on format, see: https://www.npmjs.com/package/tracer 33 | format: moduleName + ' ' + '{{timestamp}} {{file}}:{{line}} {{message}}', 34 | }); 35 | } 36 | return debugFunctions[moduleName]; 37 | }; 38 | 39 | var utilLogger = debugLogger('wcm-utils'); 40 | 41 | var getSettings = function(cwd) { 42 | cwd = cwd || process.cwd(); 43 | var settings = {}; 44 | try { 45 | settings = JSON.parse(fs.readFileSync(cwd + "/.settings").toString()); 46 | } catch (e) { 47 | } 48 | return settings; 49 | }, 50 | setSettings = function(cwd, settings) { 51 | cwd = cwd || process.cwd(); 52 | try { 53 | fs.writeFileSync(cwd + "/.settings", JSON.stringify(settings)); 54 | } catch (e) { 55 | utilLogger.error('setSettings::error::' + e); 56 | } 57 | }, 58 | getMergerdOptions = function(options, settings){ 59 | var trial = process.env.DIGEXP_TRIAL || ''; 60 | if(trial != '') 61 | options.trial = true; 62 | if(settings.options != undefined){ 63 | if(settings.options.includeMeta != undefined) 64 | options.includeMeta = settings.options.includeMeta; 65 | if(settings.options.pullParallel != undefined) 66 | options.pullParallel = settings.options.pullParallel; 67 | if(settings.options.include != undefined) 68 | options.include = settings.options.include; 69 | if(settings.options.filterComponentId != undefined) 70 | options.filterComponentId = settings.options.filterComponentId; 71 | if(settings.options.trial != undefined) 72 | options.trial = settings.options.trial; 73 | }; 74 | return options; 75 | }; 76 | 77 | 78 | module.exports.debugLogger = debugLogger; 79 | module.exports.getSettings = getSettings; 80 | module.exports.setSettings = setSettings; 81 | module.exports.getMergerdOptions = getMergerdOptions; 82 | -------------------------------------------------------------------------------- /digexp-wcm-design/lib/wcmItem.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | /** 11 | * Returns the Id of a wcmItem 12 | * @param {Object*} an wcmItem 13 | * @returns an String like "wcmrest:d369a759-36c4-4133-a8be-e426766a827e" 14 | */ 15 | function getId(item){ 16 | var id = item.id; 17 | if(item.pid != undefined) 18 | id = item.pid; 19 | return id; 20 | } 21 | 22 | /** 23 | * Returns the Type of a wcmItem 24 | * @param {Object*} an wcmItem 25 | * @returns an String like "PresentationTemplate" 26 | */ 27 | function getType(item){ 28 | var type = item.type; 29 | if(item.ptype != undefined) 30 | type = item.ptype; 31 | return type; 32 | } 33 | /** 34 | * Returns the name of a wcmItem 35 | * @param {Object*} an wcmItem 36 | * @returns an String like "Article Presentation" 37 | */ 38 | function getName(item){ 39 | var name = ""; 40 | if(item.pname != undefined) 41 | name = item.pname; 42 | else 43 | if(item.name != undefined) 44 | name = item.name; 45 | else 46 | if(item.title != undefined){ 47 | if(item.title instanceof Object){ 48 | name = item.title.value; 49 | } 50 | else 51 | name = item.title; 52 | } 53 | return name; 54 | } 55 | 56 | /** 57 | * Returns the title of a wcmItem 58 | * @param {Object*} an wcmItem 59 | * @returns an String like "Article Presentation" 60 | */ 61 | function getTitle(item){ 62 | var title = ""; 63 | if(item.title != undefined){ 64 | if(item.title instanceof Object){ 65 | title = item.title.value; 66 | } 67 | else 68 | title = item.title; 69 | } 70 | else 71 | if(item.name != undefined) 72 | title = item.name; 73 | return title; 74 | } 75 | 76 | /** 77 | * Returns the created date of a wcmItem 78 | * @param {Object*} an wcmItem 79 | * @returns an String like "Tue, 10 Mar 2015 20:09:06.769Z" 80 | */ 81 | function getCreated(item){ 82 | return item.created; 83 | } 84 | 85 | /** 86 | * Returns the last updated date of a wcmItem 87 | * @param {Object*} an wcmItem 88 | * @returns an String like "Tue, 10 Mar 2015 20:09:06.769Z" 89 | */ 90 | function getUpdated(item){ 91 | return item.updated; 92 | } 93 | 94 | /** 95 | * Returns the Content of a wcmItem 96 | * @param {Object*} an wcmItem 97 | * @returns an Object {type:"text/html",value:""} 98 | */ 99 | function getContent(item){ 100 | return item.content; 101 | } 102 | 103 | /** 104 | * Returns the path of a wcmItem 105 | * @param {Object*} an wcmItem 106 | * @returns an Object {type:"text/html",value:""} 107 | */ 108 | function getPath(item){ 109 | return item.path;; 110 | } 111 | 112 | /** 113 | * Returns the href for the requested operation of a wcmItem 114 | * @param {Object*} an wcmItem 115 | * @param String name of the operation 116 | * @returns an String like "/wps/mycontenthandler/!ut/p/digest!V32pMAeTOtOSZVI8GsXFuQ/wcmrest/PresentationTemplate/d369a759-36c4-4133-a8be-e426766a827e" 117 | */ 118 | function getOperationHref(item, opName){ 119 | var hRef = undefined; 120 | var links = item.link; 121 | if(item.plink != undefined) 122 | links = item.plink; 123 | var type = item.type; 124 | if(item.ptype != undefined) 125 | type = item.ptype; 126 | var link = getLinkForRel(type, links, opName); 127 | if(link != undefined) 128 | hRef = link.href; 129 | return hRef; 130 | } 131 | 132 | /** 133 | * Returns the content type for the requested operation of a wcmItem 134 | * @param {Object*} an wcmItem 135 | * @returns an String like 'application/vnd.ibm.wcm+xml' 136 | */ 137 | function getTypeforUpdate(item){ 138 | var type = undefined; 139 | var link = getLinkForRel(item.type, item.link,"edit-media"); 140 | if(link != undefined){ 141 | if(item.content && item.content.resourceUri && item.content.resourceUri.type) 142 | type = item.content.resourceUri.type; 143 | else 144 | type = link.type; 145 | } 146 | else if(item.content && item.content.type) 147 | type = item.content.type; 148 | return type; 149 | } 150 | 151 | function getLinkForRel(type, linkArray, relName) { 152 | var retval = null; 153 | linkArray.forEach(function(linkEntry) { 154 | // console.log('linkEntry: ' + JSON.stringify(linkEntry, null, 2)); 155 | if (linkEntry.rel === relName){ 156 | retval = linkEntry; 157 | if("edit-media" === relName){ 158 | if(type == 'LibraryStyleSheetComponent'){ 159 | if(linkEntry.type == 'text/css'){ 160 | retval = linkEntry; 161 | }; 162 | } 163 | else 164 | if(type == 'LibraryImageComponent'){ 165 | if(linkEntry.type == 'image/*'){ 166 | retval = linkEntry; 167 | }; 168 | } 169 | else 170 | if(type == 'LibraryFileComponent'){ 171 | if(linkEntry.type == '*/*'){ 172 | retval = linkEntry; 173 | }; 174 | } 175 | else 176 | retval = linkEntry; 177 | 178 | } 179 | else 180 | retval = linkEntry; 181 | } 182 | }); 183 | return retval; 184 | } 185 | 186 | exports.getId = getId; 187 | exports.getType = getType; 188 | exports.getTypeforUpdate = getTypeforUpdate; 189 | exports.getName = getName; 190 | exports.getTitle = getTitle; 191 | exports.getCreated = getCreated; 192 | exports.getUpdated = getUpdated; 193 | exports.getOperationHref = getOperationHref; 194 | exports.getLinkForRel = getLinkForRel; 195 | exports.getContent = getContent; 196 | exports.getPath = getPath; 197 | -------------------------------------------------------------------------------- /digexp-wcm-design/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digexp-wcm-design", 3 | "version": "0.1.4", 4 | "description": "WCM Designs", 5 | "main": "wcmHelper", 6 | "bin": { 7 | "dxwcmdesigns": "bin/dxwcmdesigns" 8 | }, 9 | "dependencies": { 10 | "findit": "2.0.0", 11 | "graceful-fs": "3.0.6", 12 | "hashmap": "2.0.3", 13 | "prompt": "^0.2.14", 14 | "q": "1.2.0", 15 | "tracer": "^0.8.0", 16 | "yargs": "^3.18.0" 17 | }, 18 | "devDependencies": { 19 | "chai": "^3.2.0" 20 | }, 21 | "gitHead": "05c3bbb6af4a45ada3e819ca010cc985a6bea343", 22 | "readme": "# Node.js tool prototypes for working with WCM design elements\r\n\r\n## Next prototyping tasks\r\n\r\n### GS - Initial \"push\" functionality\r\nPush files from wcm-staging area into WCM, using filenames and folder names as the WCM names, and getting component type from the JSON metadata file for the component.\r\n\r\n### JS - Initial \"list\" and \"pull\" functionality\r\nThe target is to be able to pull Components and Presentation Templates from WCM and generate files in a folder structure under wcm-staging. There would be supporting API layers below that I assume.\r\n\r\n## Notes on Lifeco designs\r\n\r\n### Test server and Lifeco example files\r\nThere is a sandbox test server provided by Arthur Lin that contains some of the Lifeco WCM code. Arthur is with ISSW working with Lifeco, and he's available for questions regarding WCM and these Lifeco scenarios.\r\n\r\nTo view the site --> http://al-ff-wp85cf5.rtp.raleigh.ibm.com/dsms/portal/ff/web/en/\r\n\r\nTo login to the backend --> http://al-ff-wp85cf5.rtp.raleigh.ibm.com/dsms/myportal/ff/web/en/\r\n\r\nCredentials: wpsadmin/wpsadmin\r\n\r\nThe files we got from Lifeco are under lifeco-files. WCM content is under sample-wcm-project/wcm-staging/ff_design (ff_design is the WCM library).\r\n\r\n\r\n", 23 | "readmeFilename": "readme.md", 24 | "_id": "digexp-wcm-design@0.0.1", 25 | "_shasum": "4353ed0538b453d193a37636d4d164607fbd3f00", 26 | "_from": "..\\..\\..\\AppData\\Local\\Temp\\npm-3600-7cfa8208\\git-cache-67a0b9c6345b\\05c3bbb6af4a45ada3e819ca010cc985a6bea343", 27 | "_resolved": "git+ssh://git@git.design.ibm.com:dxnode/digexp-wcm-design.git#05c3bbb6af4a45ada3e819ca010cc985a6bea343" 28 | } 29 | -------------------------------------------------------------------------------- /digexp-wcm-design/readme.md: -------------------------------------------------------------------------------- 1 | # Node.js tools for working with WCM design elements 2 | 3 | See readme.md for the Web Developer Toolkit for information on using these tools. 4 | 5 | ## Testing 6 | [Mocha](https://mochajs.org/) is used for running tests and [Chai](http://chaijs.com/) 7 | is used for assertions. To run the tests, first install Mocha globally, 8 | ``` 9 | $ npm install -g mocha 10 | ``` 11 | Then run `$ npm install` from the project's root folder which should install 12 | Chai as a dev dependency. Then run Mocha from the project's root folder 13 | (`digexp-toolkit/digexp-wcm-design`): 14 | ``` 15 | $ mocha 16 | ``` 17 | Some tests may fail because they took too long. The timeout length can be increased by changing 18 | the value of `LONG_TIMEOUT` in `test/wcmHelper.js`. -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Design Library.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "wcmrest:71cff676-2c3f-40b1-8a74-230ed335da67", 3 | "title": "Design Library", 4 | "summary": null, 5 | "type": "Library", 6 | "updated": "Fri, 23 Oct 2015 14:58:05.097Z", 7 | "link": [ 8 | { 9 | "rel": "edit", 10 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/71cff676-2c3f-40b1-8a74-230ed335da67", 11 | "lang": "en", 12 | "label": "Edit" 13 | }, 14 | { 15 | "rel": "alternate", 16 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/71cff676-2c3f-40b1-8a74-230ed335da67", 17 | "lang": "en", 18 | "label": "Read" 19 | }, 20 | { 21 | "rel": "library", 22 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/71cff676-2c3f-40b1-8a74-230ed335da67", 23 | "lang": "en", 24 | "label": "Library" 25 | } 26 | ], 27 | "nm": "Design_Library", 28 | "$$hashKey": "object:84", 29 | "datePulled": "Tue Jan 05 2016 14:10:02 GMT-0500 (Eastern Standard Time)" 30 | } -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "wcmrest:81dcc4a6-c822-4168-a9c4-64392ad43fec", 3 | "title": "Web Content Templates 3.0", 4 | "summary": null, 5 | "type": "Library", 6 | "updated": "Fri, 22 May 2015 01:49:52.610Z", 7 | "lastModifier": { 8 | "distinguishedName": "uid=wpsadmin,o=defaultWIMFileBasedRealm", 9 | "uri": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1", 10 | "name": "wpsadmin" 11 | }, 12 | "link": [ 13 | { 14 | "rel": "edit", 15 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/81dcc4a6-c822-4168-a9c4-64392ad43fec", 16 | "lang": "en", 17 | "label": "Edit" 18 | }, 19 | { 20 | "rel": "alternate", 21 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/81dcc4a6-c822-4168-a9c4-64392ad43fec", 22 | "lang": "en", 23 | "label": "Read" 24 | }, 25 | { 26 | "rel": "library", 27 | "href": "/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/Library/81dcc4a6-c822-4168-a9c4-64392ad43fec", 28 | "lang": "en", 29 | "label": "Library" 30 | } 31 | ], 32 | "nm": "Web_Content_Templates_3.0", 33 | "$$hashKey": "object:61", 34 | "datePulled": "Tue Dec 15 2015 05:43:08 GMT-0500 (Eastern Standard Time)" 35 | } -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Article-elements.json: -------------------------------------------------------------------------------- 1 | {"id":"wcmrest:424b45a5-de1e-48a6-83aa-c2c5a79024c6","title":{"lang":"en"},"summary":{"lang":"en"},"name":"","type":"Content","updated":"Tue, 15 Dec 2015 10:56:25.157Z","created":"Wed, 09 Feb 2011 03:39:01.904Z","lastModifier":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"creator":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"link":[{"rel":"self","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/69be310d-86b3-45dc-8956-a77725b55db9/Prototype","lang":"en","label":"Read"},{"rel":"edit","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/69be310d-86b3-45dc-8956-a77725b55db9/Prototype","lang":"en","label":"Edit"},{"rel":"edit-media","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/69be310d-86b3-45dc-8956-a77725b55db9/Prototype","type":"application/vnd.ibm.wcm+xml","lang":"en","label":"Edit Media"}],"content":{"type":"application/vnd.ibm.wcm+xml","content":{"elements":{"element":[{"name":"Body","type":"RichTextComponent","data":{"type":"text/html","value":"

 

\n"}},{"name":"preview-image","type":"FileComponent","data":{"type":"application/vnd.ibm.wcm+xml","file":""}}]}}},"ptype":"ContentTemplate","pid":"wcmrest:69be310d-86b3-45dc-8956-a77725b55db9"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Article-elements/Body_richtext.rtf: -------------------------------------------------------------------------------- 1 |

 

2 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Article-elements/preview-image_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Article-elements/preview-image_file.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Cr_reference.txt: -------------------------------------------------------------------------------- 1 | /wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/LibraryFileComponent/05319108-a752-4364-b544-05175e59b342 -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Dt_date.txt: -------------------------------------------------------------------------------- 1 | {"type":"DateTime","value":"Wed, 18 Nov 2015 06:00:00.000Z"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Filetest_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Filetest_file.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/HTMl_html.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |

WCM Design Libraries 4 | 6 |

7 |

8 | {{configInfo.wcmDesignsPath}}

9 |
10 |
{{status}}
11 |
12 | Error: 13 | Path {{configInfo.wcmDesignsPath}} not found. 14 |
15 |

Please set a WCM Design Libraries folder in settings

16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 32 |
33 |
34 |
35 |
36 |
37 | No WCM libraries found in {{configInfo.wcmDesignsPath}}. 38 |
39 |
40 |
41 |
42 |
43 |

{{wcmDesign.title}} 44 | 47 |

48 |
{{status}}
49 |
{{wcmDesign.summary}}
50 |
51 | {{wcmDesign.dateUpdated}} 52 |
53 |
54 |
55 |
56 | 62 | 63 |
64 | Pushed: {{wcmDesign.datePushed}}
65 |
66 | Pulled: {{wcmDesign.datePulled}}
67 |
68 |
69 | 72 | 75 | 78 | 97 | 101 |
102 |
103 |
104 |
105 |
106 | 107 | 111 | 112 | Wowo

-------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/JSP_jsp.txt: -------------------------------------------------------------------------------- 1 | {"path":"\\jfjdf\\red.jsp"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Link_link.txt: -------------------------------------------------------------------------------- 1 | {"destination":{"type":"content","allowClear":false,"queryString":"","value":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/LibraryImageComponent/269dbd9e-be7c-4f82-81b4-5d149e1d04db"},"display":{"type":"text","value":""},"description":{"useDestination":false,"value":""},"target":"None","additionalAttributes":""} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Number_number.txt: -------------------------------------------------------------------------------- 1 | 324 -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Opt_optionselection.txt: -------------------------------------------------------------------------------- 1 | {"displaytype":"Automatic","selection":"UserDefined","options":{"mode":"Singleselect"}} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/RichTexter_richtext.rtf: -------------------------------------------------------------------------------- 1 |

Very Rich

2 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Short Text_short.txt: -------------------------------------------------------------------------------- 1 | how short is short -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/Text_text.txt: -------------------------------------------------------------------------------- 1 | Yes Text -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/UsedSel_userselecttion.txt: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Gws bestest-elements/img_img.txt: -------------------------------------------------------------------------------- 1 | {"dimension":{"height":"326","width":"548","border":"0"},"altText":"","tagName":"","fileName":"error.png","resourceUri":{"type":"image/png","value":"/wps/wcm/myconnect/18c2f1a0-d111-4bbb-a04e-b0b0d2057c05/error.png?MOD=AJPERES"}} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Image-elements.json: -------------------------------------------------------------------------------- 1 | {"id":"wcmrest:a7ce0e8b-5a19-426d-ae41-934f02595e48","title":{"lang":"en"},"summary":{"lang":"en"},"name":"","type":"Content","updated":"Tue, 15 Dec 2015 10:56:42.419Z","created":"Wed, 18 Jan 2012 21:08:49.755Z","lastModifier":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"creator":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"link":[{"rel":"self","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/993c4713-c22b-44ab-80d8-6082979943ad/Prototype","lang":"en","label":"Read"},{"rel":"edit","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/993c4713-c22b-44ab-80d8-6082979943ad/Prototype","lang":"en","label":"Edit"},{"rel":"edit-media","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/993c4713-c22b-44ab-80d8-6082979943ad/Prototype","type":"application/vnd.ibm.wcm+xml","lang":"en","label":"Edit Media"}],"content":{"type":"application/vnd.ibm.wcm+xml","content":{"elements":{"element":[{"name":"Image","type":"ImageComponent","data":{"type":"application/vnd.ibm.wcm+xml","image":{"dimension":{"height":"","width":"","border":"0"},"altText":"","tagName":""}}},{"name":"preview-image","type":"FileComponent","data":{"type":"application/vnd.ibm.wcm+xml","file":""}}]}}},"ptype":"ContentTemplate","pid":"wcmrest:993c4713-c22b-44ab-80d8-6082979943ad"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Image-elements/Image_img.txt: -------------------------------------------------------------------------------- 1 | {"dimension":{"height":"","width":"","border":"0"},"altText":"","tagName":""} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Image-elements/preview-image_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Image-elements/preview-image_file.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/List-elements.json: -------------------------------------------------------------------------------- 1 | {"id":"wcmrest:5fdb231a-6fb7-4084-9aa4-5c1c9ee43f71","title":{"lang":"en"},"summary":{"lang":"en"},"name":"","type":"Content","updated":"Tue, 15 Dec 2015 10:56:44.370Z","created":"Wed, 09 Feb 2011 03:51:20.543Z","lastModifier":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"creator":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"link":[{"rel":"self","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/f1ee927d-7d02-413b-9822-36563d8070f3/Prototype","lang":"en","label":"Read"},{"rel":"edit","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/f1ee927d-7d02-413b-9822-36563d8070f3/Prototype","lang":"en","label":"Edit"},{"rel":"edit-media","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/f1ee927d-7d02-413b-9822-36563d8070f3/Prototype","type":"application/vnd.ibm.wcm+xml","lang":"en","label":"Edit Media"}],"content":{"type":"application/vnd.ibm.wcm+xml","content":{"elements":{"element":[{"name":"menu","type":"ReferenceComponent","data":{"type":"application/vnd.ibm.wcm+xml","reference":""}},{"name":"preview-image","type":"FileComponent","data":{"type":"application/vnd.ibm.wcm+xml","file":""}}]}}},"ptype":"ContentTemplate","pid":"wcmrest:f1ee927d-7d02-413b-9822-36563d8070f3"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/List-elements/menu_reference.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/List-elements/menu_reference.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/List-elements/preview-image_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/List-elements/preview-image_file.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Rich Text-elements.json: -------------------------------------------------------------------------------- 1 | {"id":"wcmrest:7be8035d-be36-4d5a-93da-a18413d53812","title":{"lang":"en"},"summary":{"lang":"en"},"name":"","type":"Content","updated":"Tue, 15 Dec 2015 10:56:46.447Z","created":"Wed, 18 Jan 2012 20:26:36.407Z","lastModifier":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"creator":{"distinguishedName":"uid=wpsadmin,o=defaultWIMFileBasedRealm","uri":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/um/users/profiles/Z9eAeP9PG3P8CMPDCMM071RD6MMG663ECJM4CJ1E4JMGC33EC3S86L1PCJS06J1","name":"wpsadmin"},"link":[{"rel":"self","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/330b853d-5819-4de0-9d25-eec6846949d9/Prototype","lang":"en","label":"Read"},{"rel":"edit","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/330b853d-5819-4de0-9d25-eec6846949d9/Prototype","lang":"en","label":"Edit"},{"rel":"edit-media","href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/ContentTemplate/330b853d-5819-4de0-9d25-eec6846949d9/Prototype","type":"application/vnd.ibm.wcm+xml","lang":"en","label":"Edit Media"}],"content":{"type":"application/vnd.ibm.wcm+xml","content":{"elements":{"element":[{"name":"body","type":"RichTextComponent","data":{"type":"text/html","value":"

 

\n"}},{"name":"preview-image","type":"FileComponent","data":{"type":"application/vnd.ibm.wcm+xml","file":""}}]}}},"ptype":"ContentTemplate","pid":"wcmrest:330b853d-5819-4de0-9d25-eec6846949d9"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Rich Text-elements/body_richtext.rtf: -------------------------------------------------------------------------------- 1 |

 

2 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Rich Text-elements/preview-image_file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Authoring Templates/Rich Text-elements/preview-image_file.txt -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/1106message.txt: -------------------------------------------------------------------------------- 1 | Just now, we ha -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/3297message.txt: -------------------------------------------------------------------------------- 1 | Just now, we ha -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/6161message.txt: -------------------------------------------------------------------------------- 1 | Just now, we ha -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/9785message.txt: -------------------------------------------------------------------------------- 1 | Just now, we ha -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Brief-IBM Acquires StrongLoop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Brief-IBM Acquires StrongLoop.pdf -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/HTML - Analytics.html: -------------------------------------------------------------------------------- 1 | [Plugin:Comment compute="once"] 2 | Some common microformats for active site analytics of web content 3 | [/Plugin:Comment] 4 | 5 | 6 | [Plugin:Comment compute="once"] 7 | Write the path of the content using the AnalyticsData plugin 8 | [/Plugin:Comment] 9 | [Plugin:AnalyticsData property="path" compute="once"] 10 | 11 | [Plugin:Comment compute="once"] 12 | Write the ID of the content using the AnalyticsData plugin 13 | [/Plugin:Comment] 14 | [Plugin:AnalyticsData property="id" compute="once"] 15 | 16 | [Plugin:Comment compute="once"] 17 | Write the title of the content using the AnalyticsData plugin 18 | together with a nested [Property] tag to retrieve the title. 19 | [/Plugin:Comment] 20 | [Plugin:AnalyticsData css-class="asa.wcm.content_item.title" compute="once" value="[Property context='current' type='content' field='title']"] 21 | 22 | [Plugin:Comment compute="once"] 23 | Write the date of the last modification of the content using 24 | the AnalyticsData plugin together with a nested [Property] tag 25 | to retrieve the last modification date. The date is formatted 26 | to the W3 date specification using the format attribute of the 27 | [Property] tag. 28 | [/Plugin:Comment] 29 | [Plugin:AnalyticsData css-class="asa.wcm.content_item.lastmodified" compute="once" value="[Property context='current' type='content' format='yyyy-MM-dd' field='lastmodifieddate']"] 30 | 31 | [Plugin:Comment compute="once"] 32 | Write the common names of all authors of the content as an 33 | unordered list using a [Property] tag. For example: 34 | 38 | [/Plugin:Comment] 39 | [Property context="current" type="content" separator="</li><li class="asa.wcm.content_item.authors">" field="authors" start=""] 40 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/JSPER_jsp.txt: -------------------------------------------------------------------------------- 1 | {"path":"//foo/blue"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/LibLink_link.txt: -------------------------------------------------------------------------------- 1 | {"destination":{"type":"external","allowClear":false,"value":"www.ibm.com"},"display":{"type":"text","value":"RBed"},"description":{"useDestination":false,"value":""},"target":"None","additionalAttributes":""} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Now_date.txt: -------------------------------------------------------------------------------- 1 | {"type":"DateTime","value":"Mon, 30 Nov 2015 06:00:00.000Z"} -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Number_number.txt: -------------------------------------------------------------------------------- 1 | 4,233 -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Preference JS.js: -------------------------------------------------------------------------------- 1 | var spInstanceHelper = (function() { 2 | return { 3 | getAllPreferences: function(preferencUri){ 4 | var xhrArgs = {url:preferencUri,responseType: "json"}; 5 | return i$.xhrGet(xhrArgs); 6 | }, 7 | getPortletPreferences: function (preferencUri){ 8 | Promise = i$.Promise; 9 | var p = new Promise() 10 | spInstanceHelper.getAllPreferences(preferencUri).then(function(prefJson){ 11 | var returnData = null; 12 | if(prefJson.data != null && 13 | prefJson.data.additionalPreferences['com.ibm.portal.scriptpreference'] != null) 14 | returnData = prefJson.data.additionalPreferences['com.ibm.portal.scriptpreference'][0]; 15 | if(returnData != null) 16 | returnData = JSON.parse(returnData); 17 | p.resolve(returnData); 18 | }, 19 | function(e){ 20 | p.reject(e.data); 21 | }); 22 | return p; 23 | }, 24 | setAllPreferences: function(preferencUri, prefJson){ 25 | var headers = {"Content-Type": "application/json; charset=utf-8"}; 26 | var xhrArgs = {url:preferencUri,postData:JSON.stringify(prefJson),headers: headers}; 27 | return i$.xhrPut(xhrArgs); 28 | }, 29 | setPortletPreferences: function (preferencUri, data){ 30 | Promise = i$.Promise; 31 | var p = new Promise() 32 | spInstanceHelper.getAllPreferences(preferencUri).then(function(prefJson){ 33 | var oneElement = []; 34 | oneElement[0] = JSON.stringify(data); 35 | prefJson.data.additionalPreferences['com.ibm.portal.scriptpreference'] = oneElement; 36 | spInstanceHelper.setAllPreferences(preferencUri, prefJson.data).then(function(prefJson){ 37 | var returnData = null; 38 | if(prefJson.data!= null){ 39 | returnData = JSON.parse(prefJson.data).additionalPreferences['com.ibm.portal.scriptpreference']; 40 | } 41 | if(returnData != null) 42 | returnData = JSON.parse(returnData); 43 | p.resolve(returnData); 44 | }, 45 | function(e){ 46 | p.reject(e.data); 47 | }); 48 | }, 49 | function(e){ 50 | p.reject(e.data); 51 | }); 52 | return p; 53 | } 54 | }; 55 | })(); 56 | // this is a version of promise that I can return when the other Promise support is missing 57 | // used in preview since i$ is not available always returns an error result 58 | function ErrorPromise(fn) { 59 | var value; 60 | var state = 'pending'; 61 | var deferred = null; 62 | 63 | function resolve(newValue) { 64 | if(newValue && typeof newValue.then === 'function') { 65 | newValue.then(resolve, reject); 66 | return; 67 | } 68 | state = 'resolved'; 69 | value = newValue; 70 | if(deferred) { 71 | handle(deferred); 72 | } 73 | } 74 | 75 | function reject(reason) { 76 | state = 'rejected'; 77 | value = reason; 78 | if(deferred) { 79 | handle(deferred); 80 | } 81 | } 82 | 83 | function handle(handler) { 84 | if(state === 'pending') { 85 | deferred = handler; 86 | return; 87 | } 88 | var handlerCallback; 89 | if(state === 'resolved') { 90 | handlerCallback = handler.onResolved; 91 | } else { 92 | handlerCallback = handler.onRejected; 93 | } 94 | if(!handlerCallback) { 95 | if(state === 'resolved') { 96 | handler.resolve(value); 97 | } else { 98 | handler.reject(value); 99 | } 100 | return; 101 | } 102 | 103 | var ret = handlerCallback(value); 104 | handler.resolve(ret); 105 | } 106 | 107 | this.then = function(onResolved, onRejected) { 108 | return new ErrorPromise(function(resolve, reject) { 109 | handle({ 110 | onResolved: onResolved, 111 | onRejected: onRejected, 112 | resolve: resolve, 113 | reject: reject 114 | }); 115 | }); 116 | }; 117 | fn(resolve, reject); 118 | } 119 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Rich.rtf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

VeryBig test

13 | 14 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Style alt.css: -------------------------------------------------------------------------------- 1 | #__SPNS__prefDialog { 2 | display: block; 3 | } 4 | 5 | .hide_in_view_mode { 6 | display: none; 7 | } 8 | 9 | .edit-mode .hide_in_view_mode { 10 | display: block; 11 | } 12 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/Tefer_reference.txt: -------------------------------------------------------------------------------- 1 | /wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/LibraryDateComponent/5ba6235d-7222-4db9-95ac-b41945bf09cd -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/css file-file.css: -------------------------------------------------------------------------------- 1 | #__SPNS__prefDialog { 2 | display: block; 3 | } 4 | 5 | .hide_in_view_mode { 6 | display: none; 7 | } 8 | 9 | .edit-mode .hide_in_view_mode { 10 | display: block; 11 | } 12 | -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/fred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/fred.png -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/DeleteIcon - Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/DeleteIcon - Copy.png -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/DeleteIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/DeleteIcon.png -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/EditIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/EditIcon.png -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/InfoIcon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/digexp-wcm-design/test/libraries/Web Content Templates 3.0/Components/icons/InfoIcon48.png -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Presentation Templates/Article.html: -------------------------------------------------------------------------------- 1 |
2 | 11 |

12 |
13 |
14 | [EditableProperty context="current" type="content" format="div" field="title"] 15 | [Property context="current" type="content" field="title"] 16 | [/EditableProperty] 17 |
18 |
19 |

20 |
21 |
22 |
23 | [Property context="current" type="content" awareness="true" field="creator"] 24 |  -  25 | [Property context="current" type="content" format="relative" field="lastmodifieddate"]   26 |
27 |
28 | 29 | 30 | 35 | 40 | 41 |
31 |
32 | [Plugin:tags compute="once"] 33 |
34 |
36 |
37 | [Plugin:ratings compute="once"] 38 |
39 |
42 |
43 |
44 |
45 | [EditableElement context="current" type="content" key="body"] 46 | [Element context="current" type="content" key="body"] 47 | [/EditableElement] 48 |
49 |
50 | [Plugin:AnalyticsData property="id" compute="once"] 51 | [Plugin:AnalyticsData property="title" compute="once"] 52 | [Plugin:AnalyticsData property="path" compute="once"] 53 | [Plugin:AnalyticsData property="lastmodified" compute="once"] 54 | [Plugin:AnalyticsData property="authors" compute="once"] -------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Presentation Templates/Image.html: -------------------------------------------------------------------------------- 1 |
2 | 11 | [EditableElement context="current" type="content" key="Image"] 12 | [Element context="current" type="content" key="Image" format="alt"] 13 | [/EditableElement] 14 |
-------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Presentation Templates/List of Items.html: -------------------------------------------------------------------------------- 1 |
2 | 11 |

12 | [EditableProperty context="current" type="content" format="div" field="title"] 13 | [Property context="current" type="content" field="title"] 14 | [/EditableProperty] 15 |

16 | [EditableProperty context="current" type="content" format="div" field="description"] 17 | [Property context="current" type="content" field="description"] 18 | [/EditableProperty] 19 |

20 | [Element context="current" type="content" key="menu"] 21 | [Plugin:PageMode pageMode="edit" compute="once"] 22 |

23 | 24 | [Component name="web content templates 3.0/create article"] 25 | 26 |

27 | [/Plugin:PageMode] 28 |

29 |
-------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Presentation Templates/Message.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | [Component name="web content templates 3.0/icons/infoicon48"] 6 |
7 |

[Property context="current" type="content" field="description"]

8 |
9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Presentation Templates/Rich Text.html: -------------------------------------------------------------------------------- 1 |
2 | HELLO! 3 | 12 |
13 | [EditableElement context="current" type="content" key="body"] 14 | [Element context="current" type="content" key="body"] 15 | [/EditableElement] 16 |
17 |
-------------------------------------------------------------------------------- /digexp-wcm-design/test/libraries/Web Content Templates 3.0/Workflow Items/Workflow Stages/WStage_workflowstage.txt: -------------------------------------------------------------------------------- 1 | {"option":[{"name":"ENABLE_PREVIOUS_STAGE_FOR_REVIEWERS","enabled":false},{"name":"REQUIRE_COMMENT_ON_APPROVAL","enabled":true}],"actions":{"entering":[{"href":"/wps/mycontenthandler/!ut/p/digest!EGpQWGCZ6eqbjoTMX18Tng/wcmrest/PublishAction/c2cadd90-bfcf-40a4-ad7b-3050974ec9e9"}]},"jointApproval":{"enabled":false},"workflowDefinedAccess":{"role":[{"name":"User","inheritance":true,"propagation":true},{"name":"PrivilegedUser","inheritance":true,"propagation":true},{"name":"MarkupEditor","inheritance":true,"propagation":true},{"name":"Reviewer","inheritance":true,"propagation":true},{"name":"DraftCreator","inheritance":true,"propagation":true},{"name":"Contributor","inheritance":true,"propagation":true},{"name":"Editor","inheritance":true,"propagation":true},{"name":"Manager","inheritance":true,"propagation":true},{"name":"SecurityAdmin","inheritance":true,"propagation":true},{"name":"Admin","inheritance":true,"propagation":true}]}} -------------------------------------------------------------------------------- /digexp-wcm-design/wcmHelperTest.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | 11 | wcmHelper = require('./wcmHelper'); 12 | // wcmHelper.init('gsagercf05trans.rtp.raleigh.ibm.com', 10039, '/wps/mycontenthandler', 'wpsadmin', 'wpsadmin','C:/awcm1'); 13 | wcmHelper.init('gsagerwcmdesign.rtp.raleigh.ibm.com', 10039, '/wps/mycontenthandler', 'wpsadmin', 'wpsadmin', false, 'c:\awcm1').then(function(){ 14 | try{ 15 | var libs = wcmHelper.pullLibrary('Web Content Templates 3.0').then(function(data){ 16 | console.log('Library: ', data); 17 | /* 18 | wcmHelper.pushLibrary("TestLibrary").then (function (pushedList) { 19 | console.log('pushedList: ', pushedList); 20 | } ); 21 | */ 22 | }, function(err) { 23 | console.log(err); 24 | }); 25 | 26 | } 27 | catch(e){ 28 | console.log(e); 29 | 30 | } 31 | 32 | }); 33 | // wcmHelper.init('gsagerwcmdesign.rtp.raleigh.ibm.com', 10039, '/wps/mycontenthandler', 'wpsadmin', 'wpsadmin','C:/awcm1'); 34 | 35 | /*wcmHelper.getLibraries().then(function(libs){ 36 | });*/ 37 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 IBM Corp. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * http://www.apache.org/licenses/LICENSE-2.0 6 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 8 | * specific language governing permissions and limitations under the License. 9 | */ 10 | 11 | var gulp = require("gulp"); 12 | var map = require("map-stream"); 13 | 14 | var tar = require("gulp-tar"); 15 | var gzip = require("gulp-gzip"); 16 | 17 | const WCM_DESIGNS = "./digexp-wcm-design"; 18 | const DASHBOARD = "./digexp-dashboard"; 19 | const SP_SERVER = "./digexp-sp-server"; 20 | 21 | var getFileList = function(folder) { 22 | // todo read gitignore, npmignore 23 | return [folder + "/**", "!" + folder + "/.git/**", "!" + folder + "/node_modules/**", 24 | "!" + folder + "/node_modules/", "!" + folder + "/.idea/**", "!" + folder + "/user-settings.json", + "!" + folder + "/**.*~"]; 25 | }; 26 | 27 | var npm_pack = function(folder, dest) { 28 | return gulp.src(getFileList(folder), { base: folder }) 29 | .pipe(map(function(file, cb) { 30 | // this makes sure the root folders are not included in the tar 31 | if(file.stat.isDirectory()) 32 | file.path = "package/"; 33 | else 34 | file.path = file.path.replace(file.relative, "package/" + file.relative); 35 | //console.log(file.path); 36 | cb(null, file); 37 | })) 38 | .pipe(tar(dest + ".tar")) 39 | .pipe(gzip()) 40 | .pipe(gulp.dest("./")); 41 | }; 42 | 43 | 44 | gulp.task("pack_dashboard", function() { 45 | return npm_pack(DASHBOARD, "dashboard"); 46 | }); 47 | gulp.task("pack_wcm", function() { 48 | return npm_pack(WCM_DESIGNS, "wcm-design"); 49 | }); 50 | gulp.task("pack_sp_server", function() { 51 | return npm_pack(SP_SERVER, "sp-server"); 52 | }); 53 | 54 | 55 | gulp.task('pack', ['pack_wcm', 'pack_dashboard', 'pack_sp_server']); 56 | 57 | gulp.task("watch_wcm", function() { 58 | gulp.watch(getFileList(WCM_DESIGNS), ["pack_wcm"]); 59 | }); 60 | gulp.task("watch_dashboard", function() { 61 | gulp.watch(getFileList(DASHBOARD), ["pack_dashboard"]); 62 | }); 63 | gulp.task("watch_sp-server", function() { 64 | gulp.watch(getFileList(SP_SERVER), ["pack_sp_server"]); 65 | }); 66 | 67 | gulp.task("watch", ['watch_wcm', 'watch_sp-server', 'watch_dashboard']) 68 | 69 | gulp.task('default', ['pack', 'watch']); 70 | -------------------------------------------------------------------------------- /install.cmd: -------------------------------------------------------------------------------- 1 | call npm install -g wcm-design.tar.gz 2 | call npm install -g --unsafe-perm --no-optional dashboard.tar.gz 3 | call npm install -g nw@0.12 4 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | npm install -g wcm-design.tar.gz 2 | npm install -g --unsafe-perm --no-optional dashboard.tar.gz 3 | npm install -g nw@0.12 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "digexp-toolkit", 3 | "version": "0.1.8", 4 | "devDependencies": { 5 | "grunt": "latest", 6 | "grunt-contrib-compress": "latest", 7 | "gulp": "^3.9.0", 8 | "gulp-gzip": "^1.2.0", 9 | "gulp-tar": "^1.4.0", 10 | "map-stream": "0.0.6" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /release/digexp-toolkit.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/release/digexp-toolkit.zip -------------------------------------------------------------------------------- /sp-server.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/sp-server.tar.gz -------------------------------------------------------------------------------- /uninstall.cmd: -------------------------------------------------------------------------------- 1 | call npm uninstall -g digexp-wcm-design 2 | call npm uninstall -g digexp-dashboard 3 | call npm uninstall -g nw 4 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | npm uninstall -g digexp-wcm-design 2 | npm uninstall -g digexp-dashboard 3 | npm uninstall -g nw 4 | -------------------------------------------------------------------------------- /wcm-design.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenNTF/WebDevToolkitForDx/7e24eace841c7b58caebdb0ce621a8a9ab838f4d/wcm-design.tar.gz --------------------------------------------------------------------------------