├── .gitattributes ├── .gitignore ├── AngularForms.gif ├── AngularForms ├── AngularForms.sln └── Provision.Console │ ├── App.config │ ├── App │ ├── Forms │ │ └── SampleForm │ │ │ ├── sampleController.js │ │ │ ├── sampleFields.html │ │ │ └── sampleForm.html │ ├── app.js │ ├── directives │ │ ├── choiceField.html │ │ ├── commonDirectives.js │ │ ├── datetimePicker.html │ │ ├── fileUploader.html │ │ └── radioField.html │ ├── modules │ │ ├── ng-currency.js │ │ └── peoplepicker │ │ │ ├── app.html │ │ │ ├── app.js │ │ │ ├── config │ │ │ └── config.peoplepicker.js │ │ │ ├── controllers │ │ │ └── controllers.js │ │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── scripts │ │ │ ├── angular-resource.min.js │ │ │ ├── angular-resource.min.js.map │ │ │ ├── angular-route.min.js │ │ │ ├── angular-route.min.js.map │ │ │ ├── angular-sanitize.min.js │ │ │ ├── angular-sanitize.min.js.map │ │ │ ├── angular.min.js │ │ │ └── angular.min.js.map │ │ │ └── styles │ │ │ ├── app.css │ │ │ └── bootstrap.css │ ├── services │ │ └── spFormFactory.js │ └── styles │ │ └── common.css │ ├── Extenstons │ └── StringExtentions.cs │ ├── Messager.cs │ ├── Models │ ├── Assets.cs │ ├── Attachments.cs │ └── ExcelBasedListModel.cs │ ├── PowerShell │ ├── ADD_TEST_DATA.bat │ ├── ADD_TEST_DATA.ps1 │ ├── DEPLOY_ARTIFACTS.bat │ ├── DEPLOY_ARTIFACTS.ps1 │ └── DeploymentSteps │ │ ├── ADD_TEST_DATA.ps1 │ │ ├── DEPLOYMENT_CONFIG.ps1 │ │ ├── DEPLOY_LISTS_AND_FIELDS.ps1 │ │ └── TestData │ │ └── Dental Courses.json │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Provision.Console.csproj │ ├── Releases │ └── Release package.zip │ ├── Utils │ ├── AngularHelper.cs │ ├── ContentTypeHelper.cs │ ├── ContextHelper.cs │ ├── FeaturesHelper.cs │ ├── FileHelper.cs │ ├── ListsHelper.cs │ ├── PasswordHelper.cs │ ├── SPCleaner.cs │ ├── SiteHelper.cs │ ├── WebPartsHelper.cs │ └── xField.cs │ ├── angularJs.ico │ └── packages.config ├── Deploy.jpg ├── FormSample.jpg ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 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 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /AngularForms.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms.gif -------------------------------------------------------------------------------- /AngularForms/AngularForms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.4 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Provision.Console", "Provision.Console\Provision.Console.csproj", "{A29E0A3C-9E65-4899-8B61-400FBC1E4CB1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A29E0A3C-9E65-4899-8B61-400FBC1E4CB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A29E0A3C-9E65-4899-8B61-400FBC1E4CB1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A29E0A3C-9E65-4899-8B61-400FBC1E4CB1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A29E0A3C-9E65-4899-8B61-400FBC1E4CB1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/Forms/SampleForm/sampleController.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | app.controller('MainCtrl', function ($scope, $http, $log, $location, spFormFactory) { 3 | $scope.spFormFactory = spFormFactory; 4 | 5 | spFormFactory.initialize($scope, 'LIST_TITLE').then(init); 6 | $scope.calendarFormat = 'dd-MMMM-yyyy'; 7 | 8 | $scope.saveWithButtonDisabled = function(){ 9 | $scope.hideSaveButton = 'true'; 10 | $scope.save(); 11 | } 12 | 13 | function init() { 14 | //Business logic goes here: 15 | 16 | } 17 | 18 | }); -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/Forms/SampleForm/sampleFields.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

{{f.Requestor.FieldDisplayName}}

4 |
5 |
6 | 7 | 8 |
9 |

{{f.StartDate.FieldDisplayName}}

10 | 11 |
12 | 13 | 14 |
15 |

Time

16 | 17 | {{f.StartTime.FieldDisplayName}} 18 | 19 |
20 |
21 | 22 | 23 |
24 |

Duration

25 | 26 |
27 | 28 | 29 |
30 |

{{f.WithPay.FieldDisplayName}}

31 | 32 |
33 | 34 | 35 |
36 |

Option

37 | 40 |
41 | 42 | 43 | 44 | 45 | 46 |
47 |

{{f.PhoneNumber.FieldDisplayName}}

48 | 49 |
50 | 51 | 52 |
53 |

{{f.Comments.FieldDisplayName}}

54 | 55 |
56 | 57 | 58 |
59 |

Documents:

60 | 63 | 64 | 65 | 66 | 67 |
68 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/Forms/SampleForm/sampleForm.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 |
8 |

{{ListTitle}}

9 |

10 | {{formMode}}
11 |

12 |
13 | 14 |
15 |
16 |
17 | 18 | 20 |
21 |
22 | 23 |
24 | 25 |

Attachments

26 | 27 |
28 |
29 |
30 | 31 | 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 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 80 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/app.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('app', [ 2 | 'ngSanitize', 3 | 'ngResource', 4 | 'ui.People', 5 | 'ui.bootstrap', 6 | 'ngAnimate', 7 | 'ng-currency' 8 | ]).run(function ($http) { 9 | $http.defaults.headers.common.Accept = "application/json;odata=verbose"; 10 | }); 11 | 12 | app.config(function($locationProvider){ 13 | //this allows us to get query string parameters: 14 | $locationProvider.html5Mode({ 15 | enabled: true, 16 | requireBase: false 17 | }); 18 | }) -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/directives/choiceField.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | {{ngDisabled}} 6 | 16 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/directives/commonDirectives.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | //The currently executing script file will always be the last 3 | //one in the scripts array, so you can easily find its path: 4 | var scripts = document.getElementsByTagName("script") 5 | var currentScriptPath = scripts[scripts.length-1].src; 6 | 7 | app.directive('radioField', function() { 8 | return { 9 | templateUrl: currentScriptPath.replace('commonDirectives.js', 'radioField.html'), 10 | scope: { 11 | disable: '=ngDisabled', 12 | field: '=', 13 | require: '=ngRequired' 14 | } 15 | } 16 | }); 17 | 18 | 19 | app.directive('choiceField', function() { 20 | return { 21 | templateUrl: currentScriptPath.replace('commonDirectives.js', 'choiceField.html'), 22 | scope: { 23 | disable: '=ngDisabled', 24 | field: '=', 25 | require: '=ngRequired' 26 | } 27 | } 28 | }); 29 | 30 | app.directive('datetimePicker', function() { 31 | return { 32 | templateUrl: currentScriptPath.replace('commonDirectives.js', 'datetimePicker.html'), 33 | scope: { // scope initializer.... 34 | format: '=', //= means bind it to the outside controller... 35 | model: '=ngModel', 36 | disable: '=ngDisabled', 37 | require: '=ngRequired' 38 | // ngDisabled: "=ngDisabled" 39 | }, 40 | controller: function($scope){ 41 | $scope.buttonClick = function(){ 42 | $scope.isOpen = true; 43 | } 44 | } 45 | } 46 | }); 47 | 48 | // it should be able to disable ALL inputs within a certain parent! 49 | // this way I won't need to retype ng-disable at every control 50 | 51 | //TODO: It does not work with the wrapped directives! 52 | app.directive('allInputsDisabled', function () { 53 | var allInputsDisabled = {}; 54 | allInputsDisabled.link = function (scope, element, attrs) { 55 | 56 | scope.$watch(attrs.allInputsDisabled, function (newValue) { 57 | $(element).find('input, button, select, option, textarea').prop('disabled', !!newValue); 58 | //how do I apply attribute changes to the wrapped directive? 59 | }); 60 | }; 61 | 62 | return allInputsDisabled; 63 | 64 | }); 65 | 66 | 67 | /* FILE UPLOADED DIRECTIVE */ 68 | app.directive('fileUploader', function($parse, $timeout, $q, spFormFactory) { 69 | return { 70 | templateUrl: currentScriptPath.replace('commonDirectives.js', 'fileUploader.html'), 71 | scope: { 72 | disable: '=ngDisabled', 73 | require: '=ngRequired', 74 | //parentItemId: '=', 75 | controlId: '=?', 76 | attachmentDocLibName: '=?', 77 | attachmentDocFolderName: '=?', 78 | attachmentFilterFieldName: '=?', 79 | showDisplayNameField: '=' 80 | }, 81 | 82 | link: function(scope, iElem, iAttrs) { 83 | var model = scope.model = { 84 | PENDING_CHANGE_TYPE_KEY: "PendingChangeType", 85 | PendingChangeTypeEnum: { 86 | ADD: 1, 87 | DELETE: 2 88 | }, 89 | 90 | fileReaderUnsupported: false, 91 | showDisplayNameField: (typeof(scope.showDisplayNameField) === "boolean" ? scope.showDisplayNameField : true), 92 | attachmentList: [], 93 | attachmentDisplayName: "", 94 | attachmentUniqueName: "", 95 | 96 | getParentItemId: function() { 97 | return (spFormFactory ? spFormFactory.itemId : undefined); 98 | }, 99 | 100 | getFileInputControl: function () { 101 | var fileInput = $('#' + scope.controlId + " .fileUploadControl"); 102 | return (fileInput.length <= 0 ? null : fileInput[0]); 103 | }, 104 | 105 | getAttachmentFromList: function(fileuniquename) { 106 | if (!model.attachmentList || model.attachmentList.length <= 0) return null; 107 | var existingfiles = model.attachmentList.filter(function (f) { 108 | return f.File.Name === fileuniquename; 109 | }); 110 | return (existingfiles.length > 0 ? existingfiles[0].File : null); 111 | }, 112 | 113 | 114 | // Upload the file. 115 | // You can upload files up to 2 GB with the REST API. 116 | uploadFile: function (attachment) { 117 | // Define custom metadata properties for the file before saving 118 | var customFileMetadata = {}; 119 | var parentItemId = model.getParentItemId(); 120 | if (parentItemId && parentItemId != '') customFileMetadata[scope.attachmentFilterFieldName + "Id"] = String(parentItemId); 121 | 122 | // Upload the file using the SharePoint item service 123 | return spFormFactory.uploadFileToDocLib(attachment.File.ArrayBuffer, scope.attachmentDocLibName, scope.attachmentDocFolderName, attachment.File.Name, attachment.File.Title, customFileMetadata); 124 | }, 125 | 126 | addAttachmentPending: function() { 127 | var fileInput = model.getFileInputControl(); 128 | if (!fileInput || fileInput.files.length <= 0) { 129 | console.error("No attachment to add or error locating file input control"); 130 | return; 131 | } 132 | 133 | // Assign a unique name to this file 134 | // Eventually, when adding directly to the parent list item, this can just be the file's display name 135 | model.attachmentUniqueName = spFormFactory.generateGuid() + fileInput.files[0].name.substr(fileInput.files[0].name.lastIndexOf(".")); 136 | // model.attachmentUniqueName = model.attachmentDisplayName; 137 | 138 | // Pre-load the file's contents into memory 139 | spFormFactory.getFileBuffer(fileInput) 140 | .then(function onSuccess(fileArrayBuffer) { 141 | // Prepare the new file object 142 | var newfile = model.getAttachmentFromList(model.attachmentUniqueName); 143 | if (!newfile) { 144 | newfile = { File: { 145 | Name: model.attachmentUniqueName, 146 | Title: model.attachmentDisplayName 147 | } }; 148 | } 149 | 150 | newfile.File['ArrayBuffer'] = fileArrayBuffer; 151 | newfile.File[model.PENDING_CHANGE_TYPE_KEY] = model.PendingChangeTypeEnum.ADD; 152 | 153 | // Add to the attachment list 154 | model.attachmentList.push(newfile); 155 | 156 | // Reset the file input controls 157 | fileInput.value = ''; 158 | fileInput.type = ''; 159 | fileInput.type = 'file'; 160 | 161 | model.attachmentDisplayName = ''; 162 | }); 163 | }, 164 | 165 | deleteAttachment: function(attachment) { 166 | if (typeof(attachment) !== "object" || attachment === null || typeof(attachment.File) !== "object") { 167 | console.error("Unable to locate attachment for deletion"); 168 | return; 169 | } 170 | 171 | // Mark file for deletion 172 | if (model.isServerAttachment(attachment)) attachment.File[model.PENDING_CHANGE_TYPE_KEY] = model.PendingChangeTypeEnum.DELETE; 173 | }, 174 | 175 | cancelPendingAttachmentChange: function(attachment) { 176 | if (typeof(attachment) !== "object" || attachment === null || typeof(attachment.File) !== "object") { 177 | console.error("Unable to locate attachment for cancellation"); 178 | return; 179 | } 180 | 181 | if (model.isServerAttachment(attachment)) { 182 | // Mark file for deletion 183 | attachment.File[model.PENDING_CHANGE_TYPE_KEY] = undefined; 184 | 185 | } else { 186 | // Delete from pending queue immediately 187 | var indexes = $.map(model.attachmentList, function(aFile, index) { 188 | if (aFile.File.Name === attachment.File.Name) 189 | return index; 190 | }); 191 | if (indexes.length > 0) model.attachmentList.splice(indexes[0], 1); 192 | } 193 | }, 194 | 195 | 196 | isServerAttachment: function(attachment) { 197 | return (typeof(attachment) === "object" && attachment !== null && attachment.File['ServerRelativeUrl'] !== undefined); 198 | }, 199 | 200 | isAttachmentPendingChange: function(attachment) { 201 | return (typeof(attachment) === "object" && attachment !== null && attachment.File[model.PENDING_CHANGE_TYPE_KEY] !== undefined); 202 | }, 203 | 204 | isFileSelected: function() { 205 | var fileInput = model.getFileInputControl(); 206 | var fileSelected = (fileInput && fileInput.files && fileInput.files.length > 0); 207 | 208 | 209 | return fileSelected; 210 | } 211 | }; 212 | 213 | // Ensure file reader API is supported 214 | if (!window.FileReader) model.fileReaderUnsupported = true; 215 | 216 | scope.controlId = scope.controlId || 'fileuploader'; 217 | scope.attachmentDocLibName = scope.attachmentDocLibName || 'Attachments'; 218 | scope.attachmentFilterFieldName = scope.attachmentFilterFieldName || 'ParentItemID'; 219 | scope.attachmentDocFolderName = scope.attachmentDocFolderName || ''; 220 | 221 | // Pre-populate with initial attachment list 222 | var promise = spFormFactory.loadAttachments(scope.attachmentDocLibName, scope.attachmentDocFolderName, scope.attachmentFilterFieldName, model.getParentItemId()); 223 | if (typeof(promise) === "object" && promise !== null) { 224 | promise.then(function (requestResponse) { 225 | model.attachmentList = requestResponse; 226 | }); 227 | } 228 | 229 | // Post Save Action 230 | scope.$on('spFormFactory:itemSaved', function (event, promise) { 231 | model.attachmentList.forEach(function(attachment) { 232 | // If no change pending for this attachment, skip it 233 | if (!model.isAttachmentPendingChange(attachment)) return; 234 | 235 | // If attachment is pending an addition or deletion, call the SP service to upload it and register its promise with the service 236 | if (attachment.File[model.PENDING_CHANGE_TYPE_KEY] === model.PendingChangeTypeEnum.ADD) { 237 | spFormFactory.registerPostSavePromise(promise.then(function() { return model.uploadFile(attachment); })); 238 | 239 | } else if (attachment.File[model.PENDING_CHANGE_TYPE_KEY] === model.PendingChangeTypeEnum.DELETE) { 240 | spFormFactory.registerPostSavePromise(promise.then(function() { return spFormFactory.deleteFileFromDocLib(scope.attachmentDocLibName, scope.attachmentDocFolderName, attachment.File.Name); })); 241 | } 242 | }); 243 | }); 244 | }, 245 | 246 | controller: ['$scope', function fileUploaderController($scope) { 247 | this.onFileSelected = function () { 248 | // Grab the file name from the uploader control and populate into the display name field 249 | var fileInput = $scope.model.getFileInputControl(); 250 | if (!fileInput || !fileInput.files || fileInput.files.length <= 0) return; 251 | if (typeof($scope.model.attachmentDisplayName) !== "string" || $scope.model.attachmentDisplayName.length <= 0 || !$scope.model.showDisplayNameField) { 252 | $scope.model.attachmentDisplayName = fileInput.files[0].name; 253 | } 254 | 255 | if ($scope.model.showDisplayNameField == false) { 256 | $scope.model.addAttachmentPending(); 257 | } 258 | } 259 | }] 260 | } 261 | }); 262 | 263 | // Handles pre-population of the file display name after one is selected in the file input control 264 | app.directive('onFileChanged', function ($parse) { 265 | return { 266 | // This syntax allows calls up to the parent fileUploader controller 267 | require: '^^fileUploader', 268 | 269 | link: function (scope, iElem, iAttrs, fileUploaderCtrl) { 270 | iElem.on('change', function () { 271 | var getter = $parse(iAttrs.onFileChanged); 272 | var returnValue = getter(scope, {}); 273 | 274 | 275 | 276 | }); 277 | 278 | scope.updateDisplayName = function() { 279 | // Call the parent fileUploader controller's onFileSelected() function to change the file name since the display name field is not visible in this directive 280 | fileUploaderCtrl.onFileSelected(); 281 | 282 | scope.$apply(); 283 | } 284 | } 285 | }; 286 | }); 287 | 288 | 289 | })() 290 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/directives/datetimePicker.html: -------------------------------------------------------------------------------- 1 |

2 | 12 | 13 | 14 | 17 | 18 |

19 | 29 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/directives/fileUploader.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | FileReader API not supported - file uploading will not work. Please upgrade your browser. 4 |
5 | 6 | 7 |
8 |
9 |
Select file:
10 |
11 |
12 | 13 | 14 |
15 |
16 | 17 |
18 | Name: 19 |
20 | 21 |
22 |
23 | 24 |
25 | 26 |
27 |
28 |
29 |
30 |
Existing Attachments
31 | 58 |
59 |
60 | 61 | 62 | 63 | 73 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/directives/radioField.html: -------------------------------------------------------------------------------- 1 | 2 | {{option}} 3 | 9 | 10 | 20 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/ng-currency.js: -------------------------------------------------------------------------------- 1 | !function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n(require("angular")):"function"==typeof define&&define.amd?define("ng-currency",["angular"],n):"object"==typeof exports?exports["ng-currency"]=n(require("angular")):e["ng-currency"]=n(e.angular)}(this,function(e){return function(e){function n(u){if(r[u])return r[u].exports;var o=r[u]={exports:{},id:u,loaded:!1};return e[u].call(o.exports,o,o.exports,n),o.loaded=!0,o.exports}var r={};return n.m=e,n.c=r,n.p="",n(0)}([function(e,n,r){"use strict";function u(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0});var o=r(2),i=u(o),t=r(1),a=u(t),l=i["default"].module("ng-currency",[]);l.directive("ngCurrency",a["default"]),n["default"]=l.name},function(e,n){"use strict";function r(e,n){return{require:"ngModel",link:function(r,u,o,i){function t(){if(g){var e=void 0;if(i.$options&&"blur"===i.$options.updateOn){e=i.$viewValue;for(var n=i.$parsers.length-1;n>=0;n--)e=i.$parsers[n](e)}else e=i.$$rawModelValue;for(var r=i.$formatters.length-1;r>=0;r--)e=i.$formatters[r](e);i.$viewValue=e,i.$render()}}function a(){if(i.$validate(),g){var e=l(i.$$rawModelValue);e!==i.$$rawModelValue&&(i.$setViewValue(e.toFixed(R)),i.$commitViewValue(),t())}}function l(e){return v&&(void 0!==p&&e>p?e=p:void 0!==$&&e<$&&(e=$)),e}function c(e){return RegExp("\\d|\\-|\\"+e,"g")}function d(e){return RegExp("\\-{0,1}((\\"+e+")|([0-9]{1,}\\"+e+"?))&?[0-9]{0,"+R+"}","g")}function f(r){r=String(r);var u=n.NUMBER_FORMATS.DECIMAL_SEP,o=null;r.indexOf(n.NUMBER_FORMATS.DECIMAL_SEP)===-1&&r.indexOf(".")!==-1&&R>0&&(u=".");var i=e("currency")("-1",s(),R),t=RegExp("[0-9."+n.NUMBER_FORMATS.DECIMAL_SEP+n.NUMBER_FORMATS.GROUP_SEP+"]+"),a=i.replace(t.exec(i),""),l=r.replace(t.exec(r),"");return a===l&&(r="-"+t.exec(r)),RegExp("^-[\\s]*$","g").test(r)&&(r="-0"),c(u).test(r)&&(o=r.match(c(u)).join("").match(d(u)),o=o?o[0].replace(u,"."):null),o}function s(){return void 0===x?n.NUMBER_FORMATS.CURRENCY_SYM:x}var v=void 0,$=void 0,p=void 0,x=void 0,M=void 0,g=!0,R=2;o.$observe("ngCurrency",function(e){g="false"!==e,g?t():(i.$viewValue=i.$$rawModelValue,i.$render())}),o.$observe("hardCap",function(e){v="true"===e,a()}),o.$observe("min",function(e){$=e?Number(e):void 0,a()}),o.$observe("max",function(e){p=e?Number(e):void 0,a()}),o.$observe("currencySymbol",function(e){x=e,t()}),o.$observe("ngRequired",function(e){M=e,a()}),o.$observe("fraction",function(e){R=e||2,t(),a()}),i.$parsers.push(function(e){return g&&[void 0,null,""].indexOf(e)===-1?(e=f(e),e=l(Number(e))):e}),i.$formatters.push(function(n){return g&&[void 0,null,""].indexOf(n)===-1?e("currency")(n,s(),R):n}),i.$validators.min=function(e){return!(M||[void 0,null,""].indexOf(e)===-1&&!isNaN(e))||(!g||[void 0,null].indexOf($)!==-1||isNaN($)||e>=$)},i.$validators.max=function(e){return!(M||[void 0,null,""].indexOf(e)===-1&&!isNaN(e))||(!g||[void 0,null].indexOf(p)!==-1||isNaN(p)||e<=p)},i.$validators.fraction=function(e){return!g||!e||!isNaN(e)},r.$on("currencyRedraw",function(){a(),t()}),u.bind("focus",function(){if(g){var r=new RegExp("\\"+n.NUMBER_FORMATS.GROUP_SEP,"g"),o=[void 0,null,""].indexOf(i.$$rawModelValue)===-1?e("number")(i.$$rawModelValue,R).replace(r,""):i.$$rawModelValue;i.$viewValue!==o&&(i.$viewValue=o,i.$render(),u.triggerHandler("focus"))}}),u.bind("blur",t)}}}r.$inject=["$filter","$locale"],Object.defineProperty(n,"__esModule",{value:!0}),n["default"]=r},function(n,r){n.exports=e}])}); 2 | //# sourceMappingURL=ng-currency.js.map -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
8 |
9 |
10 |

SharePoint Client-side People Picker Control

11 |
12 |
13 |
14 |
15 | 16 | Single User111: 17 | 18 |
19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 | 30 | Multiple User: 31 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 | 43 | Singe User Value: 44 | 45 |
46 |
47 |

48 |   49 |

50 |
51 |
52 |
53 |
54 | 55 | Multiple User Values: 56 | 57 |
58 |
59 |

60 | 61 |   62 | 63 |

64 |
65 |
66 |
67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 98 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | var app = angular.module('app', [ 4 | 'ngSanitize', 5 | 'ngResource', 6 | 'ui.People' 7 | ]); 8 | })(); -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/controllers/controllers.js: -------------------------------------------------------------------------------- 1 | //App Controller 2 | (function () { 3 | 'use strict'; 4 | var controllerId = 'appCtrlr'; 5 | angular.module('app').controller(controllerId, ['$scope', '$timeout', appCtrlr]); 6 | 7 | function appCtrlr($scope, $timeout) { 8 | var vm = this; 9 | vm.webUrl = null; 10 | vm.data = { 11 | su:null, 12 | mu:null 13 | }; 14 | vm.getPresence = getPresence; 15 | var service = function () { 16 | this.webAbsoluteUrl = _spPageContextInfo.webAbsoluteUrl; 17 | this.webRelativeUrl = _spPageContextInfo.webServerRelativeUrl; 18 | this.currentUserId = _spPageContextInfo.userId; 19 | this.webAppUrl = document.location.origin || document.location.href.substring(0, document.location.href.indexOf(document.location.pathname)); 20 | } 21 | 22 | init(); 23 | 24 | function init() { 25 | //Normally you would get this information from a REST call to Office 365 / SharePoint 26 | getData(); 27 | //Update the weburl property 28 | //This is to demo passing in a Web URL to the people picker via the pp-web-url attribute. 29 | $timeout(function(){ 30 | var s = new service; 31 | vm.webUrl = s.webAppUrl; 32 | if (!$scope.$root.$$phase) { 33 | $scope.$apply(); 34 | } 35 | },500); 36 | }; 37 | 38 | function getData(){ 39 | $timeout(function(){ 40 | vm.data.su = { 41 | //You'll need to add a valid claims based identity, and the SPUSER ID here 42 | Name:'i:0#.f|membership|dmolodtsov@jolera.com', 43 | Id:'22', 44 | Title:'Denis Molodtsov' 45 | }; 46 | //Add a user to the mulitple-user model 47 | vm.data.mu = {results:[]}; 48 | vm.data.mu.results.push({ 49 | //You'll need to add a valid claims based identity, and the SPUSER ID here 50 | Name:'i:0#.f|membership|dmolodtsov@jolera.com', 51 | Id:'22', 52 | Title:'Denis Molodtsov'}); 53 | //Add a SharePoint group to the mulitple-user model 54 | vm.data.mu.results.push({ 55 | //You'll need to add a valid claims based identity, and the SPUSER ID here 56 | Name:'App Center Owners', 57 | Id:'3', 58 | Title:'App Center Owners'}); 59 | if (!$scope.$root.$$phase) { 60 | $scope.$apply(); 61 | } 62 | },100) 63 | 64 | } 65 | 66 | function getPresence(userId, userTitle) { 67 | if (userId && userTitle) { 68 | return '' + userTitle + ''; 69 | } 70 | return ''; 71 | } 72 | } 73 | })(); 74 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/App/modules/peoplepicker/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/scripts/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.10 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)p.hasOwnProperty(c)&&("$"!==c.charAt(0)&&"$"!==c.charAt(1))&&(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&& 7 | b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= 8 | a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| 10 | c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); 14 | //# sourceMappingURL=angular-sanitize.min.js.map 15 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/scripts/angular-sanitize.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"angular-sanitize.min.js", 4 | "lineCount":13, 5 | "mappings":"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", 6 | "sources":["angular-sanitize.js"], 7 | "names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] 8 | } 9 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/modules/peoplepicker/styles/app.css: -------------------------------------------------------------------------------- 1 | div#strk{ 2 | background-color:inherit; 3 | font-family:Arimo; 4 | color: brown; 5 | font-size:14px; 6 | line-height:18px!important; 7 | } 8 | 9 | div#sideNavBox { 10 | display:none; 11 | } 12 | 13 | div#contentBox{ 14 | margin-left:0px; 15 | margin-right:0px; 16 | } 17 | 18 | div.ms-srch-sb{ 19 | background-color:#fff; 20 | } 21 | 22 | .srTitle{ 23 | font-family:Lobster !important; 24 | font-size: 48px; 25 | } 26 | 27 | 28 | /* People Picker Modifications */ 29 | div#strk .sp-peoplepicker-autoFillContainer{ 30 | z-index: 20; 31 | background-color:#fff; 32 | } 33 | div#strk .sp-peoplepicker-topLevel{ 34 | background-color:#fff; 35 | } 36 | div#strk .sp-peoplepicker-topLevel{ 37 | min-height:34px; 38 | } 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/services/spFormFactory.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | app.factory('spFormFactory', function($location, $http, $log, $q, $rootScope) { 3 | 4 | var spFormFactory = {}; 5 | spFormFactory.loading = false; 6 | 7 | var search = $location.search(); 8 | spFormFactory.itemId = $location.search().ID; 9 | spFormFactory.userId = _spPageContextInfo.userId; 10 | spFormFactory.userLoginName = _spPageContextInfo.userLoginName; 11 | spFormFactory.isSiteAdmin = _spPageContextInfo.isSiteAdmin; 12 | 13 | if (window.location.href.indexOf('DispForm.aspx') != -1) { 14 | spFormFactory.formMode = 'View'; 15 | } else if (window.location.href.indexOf('NewForm.aspx') != -1) { 16 | spFormFactory.formMode = 'New'; 17 | } else { 18 | spFormFactory.formMode = 'Edit'; 19 | } 20 | 21 | //INITIALIZATION START 22 | spFormFactory.initialize = function(scope, listTitle) { 23 | spFormFactory.scope = scope; 24 | scope.ListTitle = spFormFactory.ListTitle = listTitle; 25 | scope.formMode = spFormFactory.formMode; 26 | scope.save = spFormFactory.save; 27 | scope.cancel = spFormFactory.cancel; 28 | scope.userId = _spPageContextInfo.userId; 29 | 30 | //OOTB SharePoint Save button ovverride: 31 | window.PreSaveAction = function() { 32 | scope.save(); 33 | scope.$apply(); 34 | }; 35 | 36 | spFormFactory.loading = true; 37 | return getFields() 38 | .then(initializeFields) 39 | .then(getFieldValues) 40 | .then(initializeFieldValues) 41 | .then(passResultsToScope) 42 | .then(getListEntityFullName) 43 | .then(setListEntityFullName) 44 | .finally(function(){ 45 | spFormFactory.loading = false; 46 | }); 47 | } 48 | 49 | function getFields() { 50 | spFormFactory.loading = true; 51 | var restQueryUrl = _spPageContextInfo.webServerRelativeUrl + 52 | "/_api/web/lists/getbytitle('" + spFormFactory.ListTitle + "')/Fields"; 53 | return $http.get(restQueryUrl); 54 | }; 55 | 56 | function initializeField(result) { 57 | var retVal = {}; 58 | retVal.Id = result.Id; 59 | retVal.FieldDisplayName = result.Title; 60 | retVal.FieldInternalName = result.InternalName; 61 | retVal.FieldType = result.TypeAsString; 62 | retVal.Required = result.Required; 63 | retVal.ReadOnlyField = result.ReadOnlyField; 64 | if (result.Choices) { 65 | retVal.Choices = result.Choices.results; 66 | } 67 | 68 | return retVal; 69 | }; 70 | 71 | function initializeFields(response) { 72 | var results = response.data.d.results; 73 | spFormFactory.f = {}; 74 | for (var x = 0; x < results.length; x++) { 75 | // if (!results[x].ReadOnlyField) { 76 | if (!results[x].Hidden) { 77 | if (results[x].InternalName != 'ContentType') { 78 | if (results[x].InternalName != 'Attachments') { 79 | var field = initializeField(results[x]); 80 | spFormFactory.f[results[x].InternalName] = field; 81 | } 82 | } 83 | } 84 | // } 85 | } 86 | 87 | return response; 88 | } 89 | 90 | function getFieldValues() { 91 | if (spFormFactory.formMode == 'New') { 92 | return ; 93 | } 94 | var restQueryUrl = _spPageContextInfo.webServerRelativeUrl + 95 | "/_api/web/lists/getbytitle('" + spFormFactory.ListTitle + "')/Items(" + spFormFactory.itemId + ")"; 96 | return $http.get(restQueryUrl); 97 | }; 98 | 99 | function initializeFieldValues(response) { 100 | if (spFormFactory.formMode == 'New') { 101 | return; 102 | } 103 | 104 | //Saving the eTag so that we can reuse it when updating the items 105 | spFormFactory.etag = response.data.d.__metadata.etag 106 | 107 | var fields = response.data.d; 108 | spFormFactory.fieldValues = []; 109 | 110 | for (var field in spFormFactory.f) { 111 | var fieldValue = fields[spFormFactory.f[field].FieldInternalName]; 112 | if (spFormFactory.f[field].FieldType == 'User') { 113 | //All user fields have 'Id' in their Names: 114 | fieldValue = fieldValue || fields[spFormFactory.f[field].FieldInternalName + 'Id']; 115 | spFormFactory.f[field].Value = fieldValue; 116 | 117 | if (spFormFactory.f[field].Value != null) { 118 | var getUserRestURL = _spPageContextInfo.webServerRelativeUrl + "/_api/Web/GetUserById(" + spFormFactory.f[field].Value + ")"; 119 | 120 | (function(currentFieldName) { 121 | $http.get(getUserRestURL).then(function(requestResponse) { 122 | spFormFactory.f[currentFieldName].user = {}; 123 | spFormFactory.f[currentFieldName].user.Id = requestResponse.data.d.Id; 124 | spFormFactory.f[currentFieldName].user.Name = requestResponse.data.d.LoginName; 125 | spFormFactory.f[currentFieldName].user.Title = requestResponse.data.d.Title; 126 | }); 127 | })(field); 128 | } 129 | } 130 | if (spFormFactory.f[field].FieldType == 'DateTime') { 131 | if(fields[spFormFactory.f[field].FieldInternalName] != null) 132 | { 133 | var fieldValue = moment(fields[spFormFactory.f[field].FieldInternalName]).toDate(); 134 | } 135 | else { 136 | fieldValue = null; 137 | } 138 | } 139 | spFormFactory.f[field].Value = fieldValue; 140 | } 141 | } 142 | 143 | function passResultsToScope() { 144 | spFormFactory.scope.f = spFormFactory.f; 145 | } 146 | 147 | function getListEntityFullName(){ 148 | var restQueryUrl = _spPageContextInfo.webServerRelativeUrl + 149 | "/_api/web/lists/getbytitle('" + spFormFactory.ListTitle + "')/ListItemEntityTypeFullName"; 150 | return $http.get(restQueryUrl); 151 | } 152 | 153 | function setListEntityFullName(promise){ 154 | spFormFactory.ListItemEntityTypeFullName = promise.data.d.ListItemEntityTypeFullName; 155 | } 156 | //INITIALIZATION END 157 | 158 | spFormFactory.broadcastSaveEventAndWaitForSubscribersToFinish = function(promise) { 159 | // Required to support multiple uploader controls on the same form 160 | $rootScope.$broadcast('spFormFactory:itemSaved', promise); 161 | 162 | // Track all child directive's post-save promises and ensure all are resolved before next step in promise chain 163 | return promise.then(function onSuccess() { 164 | return $q.all(postsavepromises); 165 | } ); 166 | } 167 | 168 | spFormFactory.save = function() { 169 | spFormFactory.loading = true; 170 | var requestUri = ''; 171 | var header = {}; 172 | if (spFormFactory.formMode == 'New') { 173 | requestUri = _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/GetByTitle('" + spFormFactory.ListTitle + "')/items"; 174 | 175 | header = { 176 | "accept": "application/json;odata=verbose", 177 | "content-type": "application/json;odata=verbose", 178 | "X-RequestDigest": $("#__REQUESTDIGEST").val() 179 | } 180 | } else { 181 | requestUri = _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/GetByTitle('" + spFormFactory.ListTitle + "')/getItemById(" + spFormFactory.itemId + ")"; 182 | header = { 183 | "accept": "application/json;odata=verbose", 184 | "content-type": "application/json;odata=verbose", 185 | "X-RequestDigest": $("#__REQUESTDIGEST").val(), 186 | "X-HTTP-Method": "MERGE", // needed for update 187 | "IF-MATCH": spFormFactory.etag 188 | } 189 | } 190 | 191 | $log.debug(getLatestFieldValues()); 192 | var promise = $http({ 193 | url: requestUri, 194 | method: "POST", 195 | data: getLatestFieldValues(), 196 | headers: header, 197 | }).then(onSuccess, onError); 198 | 199 | promise.then(spFormFactory.broadcastSaveEventAndWaitForSubscribersToFinish.bind(null, promise)).then(spFormFactory.cancel); 200 | 201 | function onSuccess(responseData) { 202 | if (spFormFactory.formMode == 'New') { 203 | // Read back the ID of the newly-created item so it can be used in a post-save action, if necessary 204 | if (responseData && responseData.data && responseData.data.d && responseData.data.d.ID){ 205 | spFormFactory.itemId = responseData.data.d.ID; 206 | } 207 | 208 | SP.UI.Notify.addNotification("Item created.\nDon't close the form", false); 209 | 210 | } else { 211 | SP.UI.Notify.addNotification("Item updated.\nDon't close the form", false); 212 | } 213 | } 214 | 215 | function onError(error) { 216 | console.log(error); 217 | if(error.statusText == 'Precondition Failed'){ 218 | if(error.data.error.message.value.indexOf('ETag') != -1){ 219 | alert('Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.'); 220 | } 221 | else{ 222 | alert(JSON.stringify(error)); 223 | } 224 | } 225 | else{ 226 | alert(JSON.stringify(error)); 227 | } 228 | } 229 | 230 | function getLatestFieldValues() { 231 | 232 | var fieldValues = ''; 233 | for (var field in spFormFactory.f) { 234 | if(field.ReadOnlyField && field.ReadOnlyField == true){ 235 | continue; 236 | } 237 | if (spFormFactory.f[field].FieldInternalName != 'ContentType') { 238 | if (spFormFactory.f[field].FieldType == 'User') { 239 | if (angular.isUndefined(spFormFactory.f[field].user) == false) { 240 | if (spFormFactory.f[field].user != null) { 241 | fieldValues = fieldValues + 242 | "'" + spFormFactory.f[field].FieldInternalName + "Id': " + 243 | "'" + spFormFactory.f[field].user.Id + "',"; 244 | } else { 245 | fieldValues = fieldValues + 246 | "'" + spFormFactory.f[field].FieldInternalName + "Id': " + 247 | "null,"; 248 | } 249 | } 250 | 251 | } else if (spFormFactory.f[field].FieldType == 'DateTime') { 252 | if (angular.isUndefined(spFormFactory.f[field].Value) == false) { 253 | var dateTime = moment(spFormFactory.f[field].Value); 254 | var dateTimeISO = dateTime.toISOString(); //SharePoint only understands ISO date format 255 | if (dateTimeISO.toString().toLowerCase().indexOf('invalid') == -1) { 256 | fieldValues = fieldValues + 257 | "'" + spFormFactory.f[field].FieldInternalName + "': " + 258 | "'" + dateTimeISO + "',"; 259 | } 260 | } 261 | } 262 | else { 263 | //Regular fields like Text, Note, Choice, Number: 264 | if (angular.isUndefined(spFormFactory.f[field].Value) == false) { 265 | if (spFormFactory.f[field].Value != null) { 266 | 267 | if (spFormFactory.f[field].FieldType == 'Text') { 268 | if (spFormFactory.f[field].Value.toString().length > 255){ 269 | spFormFactory.f[field].Value = spFormFactory.f[field].Value.toString().substring(0, 254); 270 | } 271 | } 272 | 273 | fieldValues = fieldValues + 274 | "'" + spFormFactory.f[field].FieldInternalName + "': " + 275 | "'" + spFormFactory.f[field].Value.toString().replace(/\\/g, '\\\\').replace(/\'/g, "\\'") + "',"; 276 | } else { 277 | fieldValues = fieldValues + 278 | "'" + spFormFactory.f[field].FieldInternalName + "': " + 279 | "null,"; 280 | } 281 | } 282 | } 283 | } 284 | } 285 | var fieldValues2 = fieldValues.substring(0, fieldValues.length - 1); 286 | 287 | return "{'__metadata': " + JSON.stringify({ 288 | 'type': spFormFactory.ListItemEntityTypeFullName 289 | }) + (typeof(fieldValues2) === "string" && fieldValues2.length > 0 ? "," + fieldValues2 : "") + "}"; 290 | } 291 | } 292 | 293 | spFormFactory.cancel = function() { 294 | if(window.frameElement){ 295 | window.frameElement.cancelPopUp(); 296 | } 297 | var Source = $location.search().Source; 298 | if (Source){ 299 | window.location = Source; 300 | } 301 | else window.location = $('#DeltaPlaceHolderPageTitleInTitleArea a').first().attr('href'); 302 | 303 | } 304 | 305 | spFormFactory.getFileEndpointUri = function(serverUrl, doclibname, foldername) { 306 | if (typeof(serverUrl) !== "string" || serverUrl.length <= 0) return undefined; 307 | 308 | var serverRelativeUrlToFolder = _spPageContextInfo.webServerRelativeUrl + 309 | (typeof(doclibname) === "string" && doclibname.length > 0 ? '/' + doclibname : '') + 310 | (typeof(foldername) === "string" && foldername.length > 0 ? '/' + foldername : ''); 311 | 312 | // Construct the endpoint. 313 | return String.format( 314 | "{0}/_api/web/getfolderbyserverrelativeurl('{1}')/files", 315 | serverUrl, serverRelativeUrlToFolder); 316 | } 317 | 318 | spFormFactory.loadAttachments = function(doclibname, foldername, filterfieldname, filterfieldvalue) { 319 | if (spFormFactory.formMode == "New") return null; 320 | 321 | var folderUsed = (typeof(foldername) === "string" && foldername.length > 0); 322 | 323 | var loadAttachmentsUrl = _spPageContextInfo.webServerRelativeUrl 324 | + "/_api/web/lists/getbytitle('" + doclibname + "')/items" 325 | + "?$select=File&$expand=File" 326 | + (folderUsed ? "&$filter=" + filterfieldname + "%20eq%20" + filterfieldvalue : ''); 327 | 328 | // Place attachments on page 329 | return $http.get(loadAttachmentsUrl).then(function(requestResponse) { 330 | var attachmentList = requestResponse.data.d.results; 331 | 332 | // Remove files that are in a different folder than the one used by this instance of the control 333 | if (folderUsed) { 334 | var folderUrlMatch = decodeURIComponent(_spPageContextInfo.webServerRelativeUrl + "/" + doclibname + "/" + foldername).toLowerCase(); 335 | //attachmentList = attachmentList.filter(item => decodeURIComponent(item.File.ServerRelativeUrl).toLowerCase().startsWith(folderUrlMatch)); 336 | attachmentList = attachmentList.filter(function(item) { return decodeURIComponent(item.File.ServerRelativeUrl).toLowerCase().startsWith(folderUrlMatch); }); 337 | } 338 | 339 | //console.log(attachmentList); 340 | return attachmentList; 341 | 342 | }, onError); 343 | 344 | // Display error messages. 345 | function onError(error) { 346 | console.log(error); 347 | alert(JSON.stringify(error)); 348 | } 349 | } 350 | 351 | // Upload the file. 352 | // You can upload files up to 2 GB with the REST API. 353 | spFormFactory.uploadFileToDocLib = function (arrayBuffer, doclibname, foldername, fileuniquename, filedisplayname, customfilemetadata) { 354 | if (typeof(arrayBuffer) !== "object" || arrayBuffer === null) return; 355 | 356 | // Define the folder path for this example. 357 | var serverRelativeUrlToFolder = _spPageContextInfo.webServerRelativeUrl + '/' + doclibname + 358 | (typeof(foldername) === "string" && foldername.length > 0 ? '/' + foldername : ''); 359 | 360 | return addFileToFolder(arrayBuffer).then(function successCallback(response) { 361 | return getListItem(response.d.ListItemAllFields.__deferred.uri).then(function successCallback(response) { 362 | // Change the display name and title of the list item. 363 | return updateListItem(response.data.d.__metadata, customfilemetadata).then(function successCallback(response) { 364 | //console.log("File uploaded and updated" + (response && response.config && response.config.url ? ": " + response.config.url : '')); 365 | }, onError); 366 | }, onError); 367 | }, onError); 368 | //}, onError); 369 | 370 | // Add the file to the file collection in the Shared Documents folder. 371 | 372 | function addFileToFolder(arrayBuffer) { 373 | // Construct the endpoint. 374 | var fileCollectionEndpoint = String.format(spFormFactory.getFileEndpointUri(_spPageContextInfo.webAbsoluteUrl, doclibname, foldername) + "/add(overwrite=true, url='{0}')", fileuniquename); 375 | 376 | // Send the request and return the response. 377 | // This call returns the SharePoint file. 378 | 379 | return jQuery.ajax({ 380 | url: fileCollectionEndpoint, 381 | type: "POST", 382 | data: arrayBuffer, 383 | processData: false, 384 | headers: { 385 | "accept": "application/json;odata=verbose", 386 | "X-RequestDigest": $("#__REQUESTDIGEST").val() 387 | //,"content-length": arrayBuffer.byteLength 388 | } 389 | }); 390 | } 391 | 392 | 393 | // Get the list item that corresponds to the file by calling the file's ListItemAllFields property. 394 | function getListItem(fileListItemUri) { 395 | // Send the request and return the response. 396 | return $http.get(fileListItemUri, { 397 | headers: { "accept": "application/json;odata=verbose" } 398 | }); 399 | } 400 | 401 | // Change the display name and title of the list item. 402 | function updateListItem(itemMetadata, customFileMetadata) { 403 | // Define the list item changes. Use the FileLeafRef property to change the display name. 404 | // Assemble the file update metadata 405 | var metadata = { 406 | __metadata: { 407 | type: itemMetadata.type 408 | }, 409 | FileLeafRef: fileuniquename, 410 | Title: filedisplayname 411 | }; 412 | 413 | // Add the custom metadata fields for this file to the metadata object 414 | if (typeof(customFileMetadata) === "object") $(metadata).extend(metadata, customFileMetadata); 415 | 416 | // Send the request and return the promise. 417 | // This call does not return response content from the server. 418 | var body = JSON.stringify(metadata); 419 | return $http.post(itemMetadata.uri, body, { 420 | headers: { 421 | "X-RequestDigest": $("#__REQUESTDIGEST").val(), 422 | "content-type": "application/json;odata=verbose", 423 | "content-length": body.length, 424 | "IF-MATCH": "*", 425 | "X-HTTP-Method": "MERGE" 426 | } 427 | }); 428 | } 429 | 430 | // Display error messages. 431 | function onError(error) { 432 | console.log(error); 433 | alert(JSON.stringify(error)); 434 | } 435 | } 436 | 437 | // Get the local file as an array buffer. 438 | spFormFactory.getFileBuffer = function (fileInput) { 439 | 440 | var deferred = $q.defer(); 441 | var reader = new FileReader(); 442 | reader.onloadend = function (e) { 443 | deferred.resolve(e.target.result); 444 | } 445 | reader.onerror = function (e) { 446 | deferred.reject(e.target.error); 447 | } 448 | reader.readAsArrayBuffer(fileInput.files[0]); 449 | return deferred.promise; 450 | } 451 | 452 | 453 | spFormFactory.deleteFileFromDocLib = function(doclibname, foldername, fileuniquename) { 454 | var fileCollectionEndpoint = String.format(spFormFactory.getFileEndpointUri(_spPageContextInfo.webAbsoluteUrl, doclibname, foldername) + "('{0}')", fileuniquename); 455 | 456 | return $http.post(fileCollectionEndpoint, null, { 457 | processData: false, 458 | headers: { 459 | //"accept": "application/json;odata=verbose", 460 | //Authorization: "Bearer " + accessToken 461 | "X-RequestDigest": $("#__REQUESTDIGEST").val(), 462 | "IF-MATCH": "*", 463 | "X-HTTP-Method":"DELETE" 464 | } 465 | }); 466 | } 467 | 468 | spFormFactory.generateGuid = function () { 469 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 470 | var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); 471 | return v.toString(16); 472 | }); 473 | } 474 | 475 | // Allow child directives each to register a promise for when their post-save actions are completed 476 | // Track each of their promises and ensure all are resolved before proceeding to the cancel() function 477 | var postsavepromises = []; 478 | spFormFactory.registerPostSavePromise = function(p) { 479 | postsavepromises.push(p); 480 | } 481 | /********************************/ 482 | return spFormFactory; 483 | 484 | }); -------------------------------------------------------------------------------- /AngularForms/Provision.Console/App/styles/common.css: -------------------------------------------------------------------------------- 1 | /*Use this to modify the way the form looks when printed. Use Chrome for debugginng*/ 2 | @media print { 3 | a[href]:after { 4 | content: none !important; 5 | } 6 | #contentBox{ 7 | position:relative; 8 | top:-90px; 9 | } 10 | #formContainer { 11 | border:none !important; 12 | position:relative; 13 | top:-70px; 14 | } 15 | .btn{ 16 | display:none; 17 | } 18 | h4{ 19 | line-height: 10px; 20 | } 21 | .non-printable{ 22 | display:none !important; 23 | } 24 | #s4-titlerow, #titleAreaBox{ 25 | visibility:hidden !important; 26 | } 27 | a[href]::after { 28 | visibility:hidden !important; 29 | content: "(" attr(class) ")" !important; 30 | } 31 | } 32 | 33 | /*Hide top ribbon with buttons like 'delete', 'edit', etc. They are useless for this form*/ 34 | #s4-ribbonrow{ 35 | display: none; 36 | } 37 | 38 | /*Hide left navigation*/ 39 | div#sideNavBox { 40 | display:none; 41 | } 42 | 43 | #MSOZoneCell_WebPartWPQ2-DISABLED { 44 | display: none; 45 | } 46 | 47 | .uib-left,.uib-right{ 48 | width:35px !important; 49 | } 50 | 51 | .uib-day button, .uib-month button, .uib-year { 52 | min-width:50px; 53 | } 54 | 55 | .fields select[name='NumberOfDaysFraction'], #NumberOfDays, #NumberOfDaysFraction { 56 | width:55px; 57 | height:31px; 58 | } 59 | 60 | input { 61 | transition:all linear 0.5s; 62 | background: transparent; 63 | } 64 | 65 | /*highlight invalid, and emptry required fields*/ 66 | input.ng-invalid, select.ng-invalid, option.ng-invalid, textarea.ng-invalid, div.ng-invalid { 67 | color:black !important; 68 | background: #FAEBD7; 69 | } 70 | 71 | div.ng-invalid { 72 | color:black !important; 73 | background: #FA2; 74 | } 75 | 76 | datetime-picker.ng-invalid input{ 77 | color:red !important; 78 | } 79 | 80 | .fields input[type='radio'].ng-invalid::after{ 81 | content: "*"; 82 | color:red; 83 | font-size:18px; 84 | } 85 | 86 | /* bootstrap timepicker: */ 87 | .uib-time input, .uib-time button{ 88 | width:35px; 89 | min-width: 33px !important; 90 | } 91 | 92 | .uib-time button{ 93 | min-width: 42px !important; 94 | margin-left: 5px; 95 | padding-left: 8px; 96 | } 97 | 98 | [uib-timepicker]{ 99 | display:inline-block; 100 | } 101 | 102 | .time-span{ 103 | position:relative; 104 | bottom:13px; 105 | } 106 | /* bootstrap timepicker end */ 107 | 108 | #CloseProcess{ 109 | width: 15px; 110 | height: 15px; 111 | margin-bottom: 5px; 112 | margin-left: 7px; 113 | } 114 | .centered { 115 | position: fixed; 116 | top: 35%; 117 | left: 50%; 118 | margin-top: -50px; 119 | margin-left: -100px; 120 | } 121 | 122 | div.sp-peoplepicker-autoFillContainer { 123 | z-index: 3 124 | } 125 | 126 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak, .hidden { 127 | display: none !important; 128 | } 129 | 130 | .full-width{ 131 | width:100%; 132 | } 133 | 134 | #formContainer { 135 | border-radius: 17px; 136 | border-style: solid; 137 | border-width: 1px; 138 | border-color: #AAA; 139 | padding: 18px; 140 | margin-top:30px; 141 | } 142 | 143 | .container [type='number'] { 144 | padding-left:4px 145 | } 146 | 147 | input[type='number'] { 148 | border: solid 1px #AAA !important; 149 | height:26px; 150 | } 151 | 152 | input[disabled='disabled'], input[disabled] { 153 | background-color:#fdfdfd !important; 154 | border: solid 1px #ccc !important; 155 | color:#888 !important; 156 | } 157 | 158 | .radio-value{ 159 | position:relative; 160 | top:-3px; 161 | width:20px; 162 | height:20px; 163 | } 164 | 165 | .selectpicker{ 166 | height:27px; 167 | } 168 | 169 | .time-span{ 170 | width:80px !important; 171 | display: inline-block; 172 | margin-bottom:10px; 173 | } 174 | 175 | span.time-span { 176 | color: rgb(119,119,119); 177 | } 178 | 179 | #onetIDListForm{ 180 | margin-left:auto; 181 | margin-right:auto; 182 | } 183 | 184 | .save-btn{ 185 | float:right; 186 | } 187 | 188 | .fields textarea, 189 | .fields .sp-peoplepicker-topLevel{ 190 | width:100% !important; 191 | } 192 | 193 | .fields select{ 194 | width:100%; 195 | height:30px 196 | } 197 | 198 | .fields input[type='checkbox'], .fields input[type='radio']{ 199 | width:40px !important; 200 | } 201 | 202 | /* People Picker Modifications */ 203 | div#strk .sp-peoplepicker-autoFillContainer{ 204 | z-index: 20; 205 | background-color:#fff; 206 | } 207 | 208 | div#strk .sp-peoplepicker-topLevel{ 209 | background-color:#fff; 210 | } 211 | 212 | div#strk .sp-peoplepicker-topLevel{ 213 | min-height:34px; 214 | } 215 | 216 | div#strk{ 217 | background-color:inherit; 218 | font-family:Arimo; 219 | color: brown; 220 | font-size:14px; 221 | line-height:18px!important; 222 | } 223 | 224 | div#contentBox{ 225 | margin-left:0px; 226 | margin-right:0px; 227 | } 228 | 229 | div.ms-srch-sb{ 230 | background-color:#fff; 231 | } 232 | 233 | .srTitle{ 234 | font-family:Lobster !important; 235 | font-size: 48px; 236 | } 237 | 238 | /* People Picker Modifications */ 239 | div#strk .sp-peoplepicker-autoFillContainer{ 240 | z-index: 20; 241 | background-color:#fff; 242 | } 243 | div#strk .sp-peoplepicker-topLevel{ 244 | background-color:#fff; 245 | } 246 | div#strk .sp-peoplepicker-topLevel{ 247 | min-height:34px; 248 | } 249 | 250 | /* Date picker*/ 251 | .full button span { 252 | background-color: limegreen; 253 | border-radius: 32px; 254 | color: black; 255 | } 256 | .partially button span { 257 | background-color: orange; 258 | border-radius: 32px; 259 | color: black; 260 | } 261 | 262 | /*ANIMATIONS BEGIN*/ 263 | /* when hiding the an element */ 264 | .ng-hide-add.animate { 265 | -webkit-animation:0.3s flipOut linear; 266 | animation:0.3s flipOut linear; 267 | /*animation-direction: reverse;*/ 268 | } 269 | 270 | /* when showing the thing */ 271 | .ng-hide-remove.animate { 272 | -webkit-animation:0.5s flipInX ease; 273 | animation:0.5s flipInX ease; 274 | } 275 | 276 | @-webkit-keyframes flipOut { 277 | 0% { 278 | opacity: 1; 279 | } 280 | 281 | 100% { 282 | opacity: 0; 283 | } 284 | } 285 | 286 | @keyframes flipOut { 287 | 0% { 288 | opacity: 1; 289 | } 290 | 291 | 100% { 292 | opacity: 0; 293 | } 294 | } 295 | 296 | /* flip in */ 297 | @-webkit-keyframes flipInX { 298 | 0% { 299 | -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); 300 | transform: perspective(400px) rotate3d(1, 0, 0, 90deg); 301 | -webkit-transition-timing-function: ease-in; 302 | transition-timing-function: ease-in; 303 | opacity: 0; 304 | } 305 | 306 | 100% { 307 | -webkit-transform: perspective(400px); 308 | transform: perspective(400px); 309 | } 310 | } 311 | 312 | @keyframes flipInX { 313 | 0% { 314 | -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); 315 | -ms-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); 316 | transform: perspective(400px) rotate3d(1, 0, 0, 90deg); 317 | -webkit-transition-timing-function: ease-in; 318 | transition-timing-function: ease-in; 319 | opacity: 0; 320 | } 321 | 322 | 100% { 323 | -webkit-transform: perspective(400px); 324 | -ms-transform: perspective(400px); 325 | transform: perspective(400px); 326 | } 327 | } 328 | 329 | /* light speed out */ 330 | @-webkit-keyframes lightSpeedOut { 331 | 0% { 332 | opacity: 1; 333 | } 334 | 335 | 100% { 336 | -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); 337 | transform: translate3d(100%, 0, 0) skewX(30deg); 338 | opacity: 0; 339 | } 340 | } 341 | 342 | @keyframes lightSpeedOut { 343 | 0% { 344 | opacity: 1; 345 | } 346 | 347 | 100% { 348 | -webkit-transform: translate3d(100%, 0, 0) skewX(30deg); 349 | -ms-transform: translate3d(100%, 0, 0) skewX(30deg); 350 | transform: translate3d(100%, 0, 0) skewX(30deg); 351 | opacity: 0; 352 | } 353 | } 354 | /*ANIMATION END*/ 355 | 356 | 357 | /********** FILE UPLOADER**************/ 358 | @-webkit-keyframes greenPulse { 359 | from { background-color: #749a02; -webkit-box-shadow: 0 0 9px #333; } 360 | 50% { background-color: #91bd09; -webkit-box-shadow: 0 0 18px #91bd09; } 361 | to { background-color: #749a02; -webkit-box-shadow: 0 0 9px #333; } 362 | } 363 | 364 | :not([disabled]).glow-effect{ 365 | -webkit-animation-name: greenPulse; 366 | -webkit-animation-duration: 1s; 367 | -webkit-animation-iteration-count: infinite; 368 | } 369 | 370 | .float-right{ 371 | float:right; 372 | } 373 | .padding-top-10{ 374 | padding-top:10px; 375 | } 376 | 377 | .fa-print{ 378 | cursor: pointer; cursor: hand; 379 | } 380 | 381 | .fileUploader > div span { 382 | line-height: 34px; 383 | vertical-align: middle; 384 | } 385 | .fileUploader > div.clearfix > div { 386 | margin-bottom: 5px; 387 | } 388 | .fileUploader > div > h5 { 389 | padding-top: 10px; 390 | } 391 | .fileUploader input[type="text"] { 392 | min-width: 200px; 393 | } 394 | .fileUploader button { 395 | min-width: 0; 396 | } 397 | .fileUploader .list-group-item { 398 | padding: 0px 8px; 399 | } 400 | .fileUploader li.attachmentItem { 401 | opacity: 1; 402 | -webkit-transition: opacity 0.333s ease-out; 403 | -o-transition: opacity 0.333s ease-out; 404 | transition: opacity 0.333s ease-out; 405 | } 406 | .fileUploader li.attachmentItem.pendingChange { 407 | opacity: 0.5; 408 | } 409 | 410 | .fileUploader li.attachmentItem.pendingChange.pendingAddition { 411 | background-color: rgba(210,255,210,1); 412 | } 413 | .fileUploader li.attachmentItem.pendingChange.pendingDeletion { 414 | background-color: rgba(255,210,210,1); 415 | } 416 | 417 | .fileUploader li.attachmentItem span.glyphicon-ban-circle { 418 | opacity: .5; 419 | } 420 | .fileUploader li.attachmentItem span.glyphicon-ban-circle:hover { 421 | opacity: 1; 422 | 423 | cursor: pointer; 424 | } 425 | .fileUploader input[type="button"] { 426 | margin-left: 0; 427 | } 428 | /***************/ -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Extenstons/StringExtentions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console 9 | { 10 | public static class StringExtentions 11 | { 12 | /// 13 | /// Returns the for use of passwords. 14 | /// 15 | /// 16 | /// 17 | public static SecureString GetSecureString(this string password) 18 | { 19 | SecureString securePassWord = new SecureString(); 20 | foreach (char c in password.ToCharArray()) securePassWord.AppendChar(c); 21 | 22 | return securePassWord; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Messager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Provision.Console 8 | { 9 | public static class Messenger 10 | { 11 | public static void Output(string message, ConsoleColor color) 12 | { 13 | System.Console.ForegroundColor = color; 14 | System.Console.WriteLine(message); 15 | System.Console.ForegroundColor = ConsoleColor.DarkGray; 16 | } 17 | 18 | public static void InfoBold(string message) 19 | { 20 | Output(message, ConsoleColor.White); 21 | } 22 | 23 | public static void Info(string message) 24 | { 25 | Output(message, ConsoleColor.DarkGray); 26 | } 27 | 28 | public static void Success(string message) 29 | { 30 | Output(message, ConsoleColor.Green); 31 | } 32 | 33 | public static void Attention(string message) 34 | { 35 | System.Console.WriteLine(); 36 | Output(message, ConsoleColor.Cyan); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Models/Assets.cs: -------------------------------------------------------------------------------- 1 | using SPMeta2.Definitions; 2 | using SPMeta2.Enumerations; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Provision.Console.Models 10 | { 11 | public class Assets 12 | { 13 | public static string ListName = "Assets"; 14 | public static ListDefinition listDefinition = new ListDefinition 15 | { 16 | Title = ListName, 17 | CustomUrl = "Assets", 18 | Description = "Assets", 19 | TemplateType = BuiltInListTemplateTypeId.DocumentLibrary, 20 | EnableVersioning = true, 21 | ContentTypesEnabled = true, 22 | OnQuickLaunch = true, 23 | EnableFolderCreation = true 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Models/Attachments.cs: -------------------------------------------------------------------------------- 1 | using SPMeta2.Definitions; 2 | using SPMeta2.Enumerations; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Provision.Console.Models 10 | { 11 | public class Attachments 12 | { 13 | public static string ListName = "Attachments"; 14 | public static ListDefinition listDefinition = new ListDefinition 15 | { 16 | Title = ListName, 17 | CustomUrl = "Attachments", 18 | Description = "Attachments for the Angular forms", 19 | TemplateType = BuiltInListTemplateTypeId.DocumentLibrary, 20 | EnableVersioning = false, 21 | ContentTypesEnabled = false, 22 | OnQuickLaunch = false, 23 | EnableFolderCreation = true 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Models/ExcelBasedListModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.SharePoint.Client; 7 | using SPMeta2.Models; 8 | using SPMeta2.Syntax.Default; 9 | using SPMeta2.Syntax.Default.Modern; 10 | using SPMeta2.Syntax.Default.Utils; 11 | using SPMeta2.CSOM.Services; 12 | using SPMeta2.Definitions; 13 | using SPMeta2.Enumerations; 14 | using System.Net; 15 | using Provision.Console; 16 | using SPMeta2.CSOM.ModelHosts; 17 | using SPMeta2.Definitions.Fields; 18 | using SPMeta2.Definitions.ContentTypes; 19 | using Provision.Console.Utils; 20 | using System.Xml.Linq; 21 | using System.Xml; 22 | 23 | namespace Provision.Console.Models 24 | { 25 | public class ExcelBasedListModel 26 | { 27 | public string ContentTypeName { get; set; } 28 | public Guid ContentGuid { get; set; } 29 | public string ListName { get; set; } 30 | public string ListUrl { get; set; } 31 | public string Group { get; set; } 32 | public string CsvFilePath { get; set; } 33 | public string ListInternalName{ get; set; } 34 | 35 | 36 | public ExcelBasedListModel(string csvFilePath, string listDisplayName, string listUrl, Guid contentTypeId, string contentTypeName, string group) 37 | { 38 | CsvFilePath = csvFilePath; 39 | ListName = listDisplayName; 40 | ListUrl = listUrl; 41 | ContentGuid = contentTypeId; 42 | ContentTypeName = contentTypeName; 43 | Group = group; 44 | } 45 | 46 | public ListDefinition getListDefinition() 47 | { 48 | var listDefinition = new ListDefinition(); 49 | listDefinition.Title = ListName; 50 | listDefinition.CustomUrl = ListUrl; 51 | listDefinition.Description = ""; 52 | listDefinition.TemplateType = BuiltInListTemplateTypeId.GenericList; 53 | listDefinition.EnableVersioning = true; 54 | listDefinition.ContentTypesEnabled = true; 55 | listDefinition.OnQuickLaunch = true; 56 | listDefinition.EnableFolderCreation = false; 57 | 58 | return listDefinition; 59 | } 60 | 61 | public ContentTypeDefinition ContentTypeDefinition 62 | { 63 | get 64 | { 65 | ContentTypeDefinition contentTypeDefinition = new ContentTypeDefinition 66 | { 67 | Name = ContentTypeName, 68 | Id = ContentGuid, 69 | ParentContentTypeId = BuiltInContentTypeId.Item, 70 | Group = Group 71 | }; 72 | 73 | return contentTypeDefinition; 74 | } 75 | 76 | } 77 | 78 | List fieldDefinitions = null; 79 | List xFields = null; 80 | 81 | public List FieldDefnitions 82 | { 83 | get 84 | { 85 | if (fieldDefinitions != null) 86 | { 87 | return fieldDefinitions; 88 | } 89 | List fields = new List(); 90 | xFields = new List(); 91 | 92 | string[] records = System.IO.File.ReadAllLines(CsvFilePath); 93 | 94 | records = records.Skip(1).ToArray(); 95 | foreach (string rec in records) 96 | { 97 | string[] field = rec.Split('\t'); 98 | xField xField = new xField(field); 99 | xFields.Add(xField); 100 | fields.Add(xField.definition); 101 | } 102 | fieldDefinitions = fields; 103 | return fields; 104 | } 105 | } 106 | 107 | public string GenerateAngularView() 108 | { 109 | string templateFolder = @"App\Forms\SampleForm"; 110 | string destinationFolder = string.Format("App\\Forms\\{0}", ListInternalName); 111 | System.IO.Directory.CreateDirectory(destinationFolder); 112 | var k = FieldDefnitions; 113 | StringBuilder AngularForm = new StringBuilder(); 114 | 115 | foreach (xField field in xFields) 116 | { 117 | AngularForm.Append(field.AngularView); 118 | } 119 | 120 | System.IO.File.Delete(string.Format("App\\Forms\\{0}\\{0}Fields.html", ListInternalName)); 121 | 122 | //XElement formattedAngularForm = XElement.Parse(AngularForm.ToString()); 123 | 124 | System.IO.File.WriteAllText(string.Format("App\\Forms\\{0}\\{0}Fields.html", ListInternalName), AngularForm.ToString()); 125 | 126 | string destinationControlerFile = destinationFolder + "\\" + ListInternalName + "Controller.js"; 127 | string destinationViewFile = destinationFolder + "\\" + ListInternalName + "Form.html"; 128 | System.IO.File.Delete(destinationControlerFile); 129 | System.IO.File.Delete(destinationViewFile); 130 | System.IO.File.Copy(templateFolder + @"\sampleController.js", destinationControlerFile); 131 | System.IO.File.Copy(templateFolder + @"\sampleForm.html", destinationViewFile); 132 | 133 | string controlerText = System.IO.File.ReadAllText(destinationControlerFile); 134 | controlerText = controlerText.Replace("LIST_TITLE", ListName); 135 | System.IO.File.WriteAllText(destinationControlerFile, controlerText); 136 | 137 | string viewText = System.IO.File.ReadAllText(destinationViewFile); 138 | viewText = viewText.Replace("LIST_NAME", ListInternalName); 139 | System.IO.File.WriteAllText(destinationViewFile, viewText); 140 | 141 | return AngularForm.ToString(); 142 | } 143 | 144 | public List GetAllFieldNames() 145 | { 146 | var fieldNames = FieldDefnitions.Select(x => x.InternalName).ToList(); 147 | return fieldNames; 148 | } 149 | 150 | public List GetAllFieldIds() 151 | { 152 | var fieldIds = FieldDefnitions.Select(x => x.Id).ToList(); 153 | return fieldIds; 154 | } 155 | public List FieldLinkValues() 156 | { 157 | var fieldIds = FieldDefnitions.Select(x => new FieldLinkValue { Id = x.Id }).ToList(); 158 | return fieldIds; 159 | } 160 | 161 | public void InjectModelsToDefinition(WebModelNode webDefinition) 162 | { 163 | webDefinition.AddFields(FieldDefnitions); 164 | webDefinition.AddContentType(ContentTypeDefinition, contentType => 165 | { 166 | contentType 167 | .AddContentTypeFieldLinks(FieldDefnitions) 168 | .AddUniqueContentTypeFieldsOrder(new UniqueContentTypeFieldsOrderDefinition 169 | { 170 | Fields = FieldLinkValues() 171 | }); 172 | }); 173 | webDefinition.AddList(this.getListDefinition(), list => 174 | { 175 | list 176 | .AddContentTypeLink(ContentTypeDefinition) 177 | .AddUniqueContentTypeOrder(new UniqueContentTypeOrderDefinition 178 | { 179 | ContentTypes = new List 180 | { 181 | new ContentTypeLinkValue{ ContentTypeName = ContentTypeDefinition.Name}, 182 | } 183 | }) 184 | ; 185 | }); 186 | } 187 | 188 | } 189 | } 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/ADD_TEST_DATA.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell.exe -Command "& '%~dpn0.ps1' -path '%~dp0'" 3 | REM PAUSE -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/ADD_TEST_DATA.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$Path 3 | ) 4 | 5 | 6 | Write-Host $Path -ForegroundColor Green 7 | . .\DeploymentSteps\DEPLOYMENT_CONFIG.ps1 8 | . .\DeploymentSteps\ADD_TEST_DATA.ps1 -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DEPLOY_ARTIFACTS.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell.exe -Command "& '%~dpn0.ps1' -path '%~dp0'" 3 | REM PAUSE -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DEPLOY_ARTIFACTS.ps1: -------------------------------------------------------------------------------- 1 |  param ( 2 | [string]$Path 3 | ) 4 | 5 | Write-Host $Path -ForegroundColor Green 6 | . .\DeploymentSteps\DEPLOYMENT_CONFIG.ps1 7 | . .\DeploymentSteps\DEPLOY_LISTS_AND_FIELDS.ps1 8 | . .\DeploymentSteps\ADD_TEST_DATA.ps1 9 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DeploymentSteps/ADD_TEST_DATA.ps1: -------------------------------------------------------------------------------- 1 | $list = Get-PnPList -Identity "Courses" -Include ItemCount 2 | if ($list.ItemCount -eq 0) { 3 | # schema: https://www.mockaroo.com/schemas/115529 4 | $courses = Get-Content -Raw -Path "DeploymentSteps\TestData\Dental Courses.json" | ConvertFrom-Json 5 | foreach ($course in $courses) { 6 | $hashTable = @{} 7 | $course.psobject.properties | ForEach-Object { $hashTable[$_.Name] = $_.Value } 8 | Add-PnPListItem -List "Courses" -Values $hashTable 9 | } 10 | } -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DeploymentSteps/DEPLOYMENT_CONFIG.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop"; 2 | 3 | Clear-Host 4 | 5 | if ($path -ne $null){ 6 | Set-Location $path 7 | Write-Host $path 8 | } 9 | 10 | if($TARGET_SITE_URL -eq $null -or [String]::IsNullOrEmpty($TARGET_SITE_URL)){ 11 | [void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') 12 | $title = 'SITE URL' 13 | $msg = 'Enter full site url:' 14 | $TARGET_SITE_URL = [Microsoft.VisualBasic.Interaction]::InputBox($msg, $title) 15 | 16 | $TARGET_SITE_URL = $TARGET_SITE_URL.Trim('/'); 17 | 18 | $uri = [System.Uri]$TARGET_SITE_URL 19 | $SERVER_RELATIVE_WEB = $uri.AbsolutePath 20 | 21 | if ($TARGET_SITE_URL -eq $null -or $TARGET_SITE_URL -eq ""){ 22 | exit 23 | Throw "no URL supplied. Exiting the script" 24 | } 25 | 26 | $credentials = Get-Credential 27 | 28 | if ($credentials -ne $null){ 29 | Connect-PnPOnline $TARGET_SITE_URL -Credentials $credentials 30 | } 31 | else{ 32 | Connect-PnPOnline $TARGET_SITE_URL -CurrentCredentials 33 | } 34 | } 35 | 36 | $web = Get-PnPWeb 37 | $web.ServerRelativeUrl 38 | 39 | Write-Host "Connected to the site:" $web.ServerRelativeUrl -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DeploymentSteps/DEPLOY_LISTS_AND_FIELDS.ps1: -------------------------------------------------------------------------------- 1 | function CreateList($ListProps) { 2 | $NewList = Get-PnPList -Identity $ListProps.Title -Includes Fields 3 | if ($NewList -eq $null) { 4 | Write-host Creating list $ListProps.Title 5 | $NewList = New-PnPList -Title $ListProps.Title -Template GenericList -Url "Lists/$($ListProps.Name)" 6 | $NewList = Get-PnPList -Identity $ListProps.Name -Includes Fields 7 | } 8 | return $NewList 9 | } 10 | 11 | function CreateField($NewFieldProps) { 12 | $NewField = ($NewFieldProps.List.Fields) | Where-Object {$_.InternalName -eq $NewFieldProps.Name} 13 | if ($NewField -eq $null) { 14 | Write-host Adding field $NewFieldProps.Name 15 | if ($NewFieldProps.Type -eq "Choice") { 16 | $NewField = Add-PnPField -List $ListProps.Title -DisplayName $NewFieldProps.Title -InternalName $NewFieldProps.Name -Type $NewFieldProps.Type -Choices $NewFieldProps.Choices -AddToDefaultView 17 | } 18 | else { 19 | $NewField = Add-PnPField -List $ListProps.Title -DisplayName $NewFieldProps.Title -InternalName $NewFieldProps.Name -Type $NewFieldProps.Type -AddToDefaultView 20 | } 21 | 22 | $NewField = ($NewFieldProps.List.Fields) | Where-Object {$_.InternalName -eq $NewFieldProps.Name} 23 | } 24 | } 25 | 26 | $ListProps = @{Name = "Courses"; Title = "Courses"} 27 | $NewList = CreateList $ListProps 28 | CreateField @{List = $NewList; Name = "Description"; Title = "Description"; Type = "Note"} 29 | CreateField @{List = $NewList; Name = "CourseType"; Title = "Course Type"; Type = "Choice"; Choices = "Webinar", "Seminar", "Other"} 30 | CreateField @{List = $NewList; Name = "Price"; Title = "Price"; Type = "Text"; } 31 | CreateField @{List = $NewList; Name = "Level"; Title = "Level"; Type = "Text"; } 32 | CreateField @{List = $NewList; Name = "Active"; Title = "Active"; Type = "Boolean"; } -------------------------------------------------------------------------------- /AngularForms/Provision.Console/PowerShell/DeploymentSteps/TestData/Dental Courses.json: -------------------------------------------------------------------------------- 1 | [{"Title":"streamline cross-media e-commerce","Description":"Aliquam non mauris. Morbi non lectus. Aliquam sit amet diam in magna bibendum imperdiet. Nullam orci pede, venenatis non, sodales sed, tincidunt eu, felis. Fusce posuere felis sed lacus. Morbi sem mauris, laoreet ut, rhoncus aliquet, pulvinar sed, nisl. Nunc rhoncus dui vel sem. Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus. Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem. Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio. Cras mi pede, malesuada in, imperdiet et, commodo vulputate, justo.","CourseType":"Webinar","Price":"$1053.84","Level":100,"Active":1}, 2 | {"Title":"streamline transparent web services","Description":"Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem. Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat. Praesent blandit. Nam nulla. Integer pede justo, lacinia eget, tincidunt eget, tempus vel, pede. Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem. Fusce consequat. Nulla nisl. Nunc nisl.","CourseType":"Seminar","Price":"$375.83","Level":100,"Active":0}, 3 | {"Title":"whiteboard bricks-and-clicks deliverables","Description":"Nulla tempus. Vivamus in felis eu sapien cursus vestibulum. Proin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem. Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit. Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque. Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus. In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst. Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat.","CourseType":"Other","Price":"$762.51","Level":300,"Active":1}, 4 | {"Title":"empower best-of-breed supply-chains","Description":"In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem. Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit. Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque. Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus. In sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst. Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem. Integer tincidunt ante vel ipsum.","CourseType":"Webinar","Price":"$970.16","Level":200,"Active":1}, 5 | {"Title":"mesh revolutionary supply-chains","Description":"Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus. Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst. Maecenas ut massa quis augue luctus tincidunt. Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem. Integer tincidunt ante vel ipsum. Praesent blandit lacinia erat. Vestibulum sed magna at nunc commodo placerat. Praesent blandit.","CourseType":"Seminar","Price":"$411.46","Level":300,"Active":0} 6 | ] -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using Provision.Console.Models; 3 | using Provision.Console.Utils; 4 | using SPMeta2.CSOM.Services; 5 | using SPMeta2.Definitions.Fields; 6 | using SPMeta2.Syntax.Default; 7 | using System; 8 | 9 | namespace Provision.Console 10 | { 11 | class Program 12 | { 13 | public const string SourceFolder = "App"; 14 | public const string AppDestinationLibraryTitle = "Assets"; 15 | public const string AssetsLibraryInternalname = "Assets"; 16 | 17 | static void Main(string[] args) 18 | { 19 | Introduction(); 20 | Messenger.Attention("Enter target site URL:"); 21 | Messenger.Info("Example: https://contoso.sharepoint.com/portal or http://SP2013Portal/subsite/"); 22 | System.Console.Write("URL: "); 23 | string targetSiteUrl = System.Console.ReadLine(); 24 | 25 | Messenger.Attention("Enter login:"); 26 | Messenger.InfoBold("Examples:"); 27 | Messenger.Info("SharePoint Online: JohnP@portal.onmicrosoft.com"); 28 | Messenger.Info("SharePoint Online: JohnPy@contoso.com"); 29 | Messenger.Info("SharePoint 2013/2016: contoso\\johnP"); 30 | System.Console.Write("Login: "); 31 | string userLogin = System.Console.ReadLine(); 32 | 33 | var clientContext = ContextHelper.GetClientContext(targetSiteUrl, userLogin); 34 | 35 | Messenger.Attention("Enter target list Title:"); 36 | System.Console.Write("List title: "); 37 | string targetListTitle = System.Console.ReadLine(); 38 | 39 | List targetList = clientContext.Web.Lists.GetByTitle(targetListTitle); 40 | clientContext.Load(targetList); 41 | clientContext.ExecuteQuery(); 42 | 43 | DeployAttachmentsLibrary(clientContext, targetList); 44 | 45 | AngularHelper.GenerateView(clientContext, targetList); 46 | 47 | FileHelper.UploadFoldersRecursively(clientContext, SourceFolder, AppDestinationLibraryTitle); 48 | 49 | WebPartsHelper.AddCEWPToList(clientContext, targetList); 50 | 51 | //Open freshly generated Form in the browser: 52 | System.Diagnostics.Process.Start(new Uri(clientContext.Web.Url).GetLeftPart(UriPartial.Authority) + "/" + targetList.DefaultNewFormUrl); 53 | } 54 | 55 | private static void DeployAttachmentsLibrary(ClientContext clientContext, List targetList) 56 | { 57 | var csomProvisionService = new CSOMProvisionService(); 58 | 59 | var webModel = SPMeta2Model.NewWebModel(); 60 | webModel.AddList(Assets.listDefinition); 61 | 62 | csomProvisionService.DeployWebModel(clientContext, webModel); 63 | 64 | var attachmentsFieldDefinition = new LookupFieldDefinition 65 | { 66 | Title = "ParentItemID", 67 | InternalName = "ParentItemID", 68 | Group = "Angular", 69 | Id = new Guid("FEF440A7-3228-4034-BB2A-FFD538D46A62"), 70 | LookupListTitle = targetList.Title, 71 | LookupWebId = clientContext.Web.Id, 72 | LookupField = "ID", 73 | RelationshipDeleteBehavior = "Cascade", 74 | Indexed = true 75 | }; 76 | 77 | var lookupFieldModel = SPMeta2Model.NewWebModel(web => 78 | { 79 | web.AddField(attachmentsFieldDefinition); 80 | }); 81 | 82 | webModel.AddList(Attachments.listDefinition, list => list.AddField(attachmentsFieldDefinition)); 83 | csomProvisionService.DeployWebModel(clientContext, webModel); 84 | } 85 | 86 | 87 | private static void Introduction() 88 | { 89 | Messenger.Attention("*****************************************************************************"); 90 | Messenger.Success("Angular Forms Generator"); 91 | Messenger.InfoBold("Automatically Generates an Angular.js form for a specified SharePoint list"); 92 | Messenger.Attention("*****************************************************************************"); 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Provision.Console")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Provision.Console")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a29e0a3c-9e65-4899-8b61-400fbc1e4cb1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Provision.Console.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A29E0A3C-9E65-4899-8B61-400FBC1E4CB1} 8 | Exe 9 | Properties 10 | Provision.Console 11 | Generate Angular Form 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | angularJs.ico 37 | 38 | 39 | 40 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.Office.Client.Policy.dll 41 | True 42 | 43 | 44 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.Office.Client.TranslationServices.dll 45 | True 46 | 47 | 48 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.Office.SharePoint.Tools.dll 49 | True 50 | 51 | 52 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.Online.SharePoint.Client.Tenant.dll 53 | True 54 | 55 | 56 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.ProjectServer.Client.dll 57 | True 58 | 59 | 60 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.dll 61 | True 62 | 63 | 64 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.DocumentManagement.dll 65 | True 66 | 67 | 68 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Publishing.dll 69 | True 70 | 71 | 72 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Runtime.dll 73 | True 74 | 75 | 76 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Runtime.Windows.dll 77 | True 78 | 79 | 80 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Search.dll 81 | True 82 | 83 | 84 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Search.Applications.dll 85 | True 86 | 87 | 88 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.Taxonomy.dll 89 | True 90 | 91 | 92 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.UserProfiles.dll 93 | True 94 | 95 | 96 | ..\packages\Microsoft.SharePointOnline.CSOM.16.1.5626.1200\lib\net45\Microsoft.SharePoint.Client.WorkflowServices.dll 97 | True 98 | 99 | 100 | ..\packages\SPMeta2.Core.1.2.95-beta3\lib\net45\SPMeta2.dll 101 | True 102 | 103 | 104 | ..\packages\SPMeta2.CSOM.Foundation.1.2.95-beta3\lib\net45\SPMeta2.CSOM.dll 105 | True 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | xcopy /s /d /y /i "$(ProjectDir)App" "$(TargetDir)App" 187 | 188 | 195 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Releases/Release package.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/Releases/Release package.zip -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/AngularHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using Provision.Console.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Provision.Console.Utils 10 | { 11 | public class AngularHelper 12 | { 13 | public static void GenerateView(ClientContext clientContext, List list) 14 | { 15 | clientContext.Load(list, x => x.RootFolder.Name); 16 | clientContext.ExecuteQuery(); 17 | 18 | ListsHelper.GenerateListCsv(clientContext, list, list.Title + ".csv"); 19 | clientContext.Load(list, x => x.DefaultDisplayFormUrl); 20 | clientContext.Load(list, x => x.DefaultNewFormUrl); 21 | clientContext.Load(list, x => x.DefaultEditFormUrl); 22 | clientContext.ExecuteQuery(); 23 | var listModel = new ExcelBasedListModel(@"Models\" + list.Title + ".csv", list.Title, list.DefaultDisplayFormUrl, new Guid("79658c1e-3096-5544-5535-4335501a5b96"), "", ""); 24 | listModel.ListInternalName = list.RootFolder.Name; 25 | listModel.GenerateAngularView(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/ContentTypeHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class ContentTypeHelper 11 | { 12 | public static void SetDocumentTemplateForConentType(ClientContext clientContext, string DeploymentContentTypeId, string wordTemplateUrl) 13 | { 14 | clientContext.Load(clientContext.Web.ContentTypes); 15 | ContentType ct = clientContext.Web.ContentTypes.GetById(DeploymentContentTypeId); 16 | clientContext.Load(ct); 17 | clientContext.ExecuteQuery(); 18 | ct.DocumentTemplate = wordTemplateUrl; 19 | ct.Update(true); 20 | 21 | clientContext.ExecuteQuery(); 22 | } 23 | 24 | public static void RemoveContentType(ClientContext clientContext, string listDisplayName, string contentTypeName) 25 | { 26 | List list = clientContext.Web.Lists.GetByTitle(listDisplayName); 27 | clientContext.Load(list.ContentTypes); 28 | clientContext.ExecuteQuery(); 29 | ContentType contentType = list.ContentTypes.FirstOrDefault(ct => ct.Name == contentTypeName); 30 | 31 | if (contentType != null) 32 | { 33 | contentType.DeleteObject(); 34 | clientContext.ExecuteQuery(); 35 | } 36 | } 37 | 38 | public static void RemoveContentType(ClientContext clientContext, Web web, string contentTypeName) 39 | { 40 | clientContext.Load(web.ContentTypes); 41 | clientContext.ExecuteQuery(); 42 | ContentType contentType = web.ContentTypes.FirstOrDefault(ct => ct.Name == contentTypeName); 43 | 44 | if (contentType != null) 45 | { 46 | contentType.DeleteObject(); 47 | clientContext.ExecuteQuery(); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/ContextHelper.cs: -------------------------------------------------------------------------------- 1 | using Provision.Console; 2 | using Microsoft.SharePoint.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Security; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Provision.Console.Utils 12 | { 13 | public class ContextHelper 14 | { 15 | public static ClientContext GetClientContext(string siteUrl, string user) 16 | { 17 | SecureString securePassword = PasswordHelper. 18 | GetPasswordFromConsoleInput(); 19 | return GetClientContext(siteUrl, user, securePassword); 20 | } 21 | public static ClientContext GetClientContext(string siteUrl, string user, string password) 22 | { 23 | SecureString securePassword = StringExtentions.GetSecureString(password); 24 | return GetClientContext(siteUrl, user, securePassword); 25 | } 26 | public static ClientContext GetClientContext(string siteUrl, string user, SecureString password) 27 | { 28 | bool onPrem = true; 29 | 30 | if (siteUrl.Contains("sharepoint.com")) 31 | { 32 | onPrem = false; 33 | } 34 | 35 | System.Console.WriteLine(); 36 | System.Console.WriteLine("Current domain: {0}", Environment.UserDomainName); 37 | 38 | ClientContext clientContext = new ClientContext(siteUrl); 39 | clientContext.AuthenticationMode = ClientAuthenticationMode.Default; 40 | 41 | if (onPrem) 42 | { 43 | clientContext.Credentials = new NetworkCredential(user, password); 44 | } 45 | else 46 | { 47 | clientContext.Credentials = new SharePointOnlineCredentials(user, password); 48 | } 49 | 50 | clientContext.Load(clientContext.Web); 51 | clientContext.ExecuteQuery(); 52 | System.Console.ForegroundColor = ConsoleColor.Green; 53 | System.Console.WriteLine("Connected to the site: {0} | {1}", clientContext.Web.Title, siteUrl); 54 | System.Console.ForegroundColor = ConsoleColor.White ; 55 | 56 | return clientContext; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/FeaturesHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class FeaturesHelper 11 | { 12 | 13 | public static void ActivateFeature(ClientContext clientContext, Site site, Guid featureId) 14 | { 15 | var features = site.Features; 16 | features.Add(featureId, true, FeatureDefinitionScope.None); 17 | 18 | try 19 | { 20 | clientContext.ExecuteQuery(); 21 | } 22 | catch (Exception) 23 | { 24 | //TODO: 25 | } 26 | } 27 | 28 | public static void ActivateFeature(ClientContext clientContext, Web web, Guid featureId) 29 | { 30 | var features = web.Features; 31 | features.Add(featureId, true, FeatureDefinitionScope.None); 32 | 33 | try 34 | { 35 | clientContext.ExecuteQuery(); 36 | } 37 | catch (Exception) 38 | { 39 | //TODO: 40 | } 41 | } 42 | 43 | public static void DeactivateFeature(ClientContext clientContext, Guid featureId) 44 | { 45 | Web web = clientContext.Web; 46 | var features = web.Features; 47 | clientContext.Load(features); 48 | clientContext.ExecuteQuery(); 49 | 50 | web.Features.Remove(featureId, true); 51 | try 52 | { 53 | clientContext.ExecuteQuery(); 54 | } 55 | catch (Exception) 56 | { 57 | //TODO: avoid try/catch 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/FileHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Provision.Console.Utils 10 | { 11 | public class FileHelper 12 | { 13 | public static void UploadDocument(ClientContext clientContext, string sourceFilePath, string serverRelativeDestinationPath) 14 | { 15 | using (var fs = new FileStream(sourceFilePath, FileMode.Open)) 16 | { 17 | var fi = new FileInfo(sourceFilePath); 18 | Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, serverRelativeDestinationPath , fs, true); 19 | } 20 | } 21 | 22 | public static void UploadFolder(ClientContext clientContext, System.IO.DirectoryInfo folderInfo, Folder folder) 23 | { 24 | System.IO.FileInfo[] files = null; 25 | System.IO.DirectoryInfo[] subDirs = null; 26 | 27 | try 28 | { 29 | files = folderInfo.GetFiles("*.*"); 30 | } 31 | catch (UnauthorizedAccessException e) 32 | { 33 | System.Console.WriteLine(e.Message); 34 | } 35 | 36 | catch (System.IO.DirectoryNotFoundException e) 37 | { 38 | System.Console.WriteLine(e.Message); 39 | } 40 | 41 | if (files != null) 42 | { 43 | foreach (System.IO.FileInfo fi in files) 44 | { 45 | System.Console.WriteLine(fi.FullName); 46 | clientContext.Load(folder); 47 | clientContext.ExecuteQuery(); 48 | UploadDocument(clientContext, fi.FullName, folder.ServerRelativeUrl + "/" + fi.Name); 49 | } 50 | 51 | subDirs = folderInfo.GetDirectories(); 52 | 53 | foreach (System.IO.DirectoryInfo dirInfo in subDirs) 54 | { 55 | Folder subFolder = folder.Folders.Add(dirInfo.Name); 56 | clientContext.ExecuteQuery(); 57 | UploadFolder(clientContext, dirInfo, subFolder); 58 | } 59 | } 60 | } 61 | 62 | public static void UploadFoldersRecursively(ClientContext clientContext, string sourceFolder, string destinationLigraryTitle) 63 | { 64 | Web web = clientContext.Web; 65 | var query = clientContext.LoadQuery(web.Lists.Where(p => p.Title == destinationLigraryTitle)); 66 | clientContext.ExecuteQuery(); 67 | List documentsLibrary = query.FirstOrDefault(); 68 | var folder = documentsLibrary.RootFolder; 69 | System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(sourceFolder); 70 | 71 | clientContext.Load(documentsLibrary.RootFolder); 72 | clientContext.ExecuteQuery(); 73 | 74 | folder = documentsLibrary.RootFolder.Folders.Add(di.Name); 75 | clientContext.ExecuteQuery(); 76 | 77 | FileHelper.UploadFolder(clientContext, di, folder); 78 | } 79 | 80 | public static void DownloadLibrary(ClientContext clientContext, string LibraryTitle, string destinationFolder) 81 | { 82 | var web = clientContext.Web; 83 | clientContext.Load(web); 84 | clientContext.ExecuteQuery(); 85 | List list = web.Lists.GetByTitle(LibraryTitle); 86 | clientContext.Load(list); 87 | clientContext.ExecuteQuery(); 88 | clientContext.Load(list.RootFolder); 89 | clientContext.ExecuteQuery(); 90 | clientContext.Load(list.RootFolder.Folders); 91 | clientContext.ExecuteQuery(); 92 | DownloadFilesFromFolder(clientContext, list.RootFolder, destinationFolder); 93 | } 94 | 95 | public static void DownloadFilesFromFolder(ClientContext clientContext, Folder folder, string destinationFolder) 96 | { 97 | string siteUrl = (new Uri(clientContext.Web.Url)).PathAndQuery; 98 | string localDestinationFolder = destinationFolder + "/" + folder.ServerRelativeUrl.Replace(siteUrl, string.Empty); 99 | localDestinationFolder = (new Uri(localDestinationFolder)).LocalPath; 100 | if (!Directory.Exists(localDestinationFolder)) 101 | { 102 | Directory.CreateDirectory(localDestinationFolder); 103 | System.Console.WriteLine("Created Folder: {0}", localDestinationFolder); 104 | } 105 | 106 | clientContext.Load(folder.Files); 107 | clientContext.ExecuteQuery(); 108 | foreach (Microsoft.SharePoint.Client.File file in folder.Files) 109 | { 110 | Stream fs = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, file.ServerRelativeUrl).Stream; 111 | byte[] binary = getByteArray(fs); 112 | string destinationFileName = localDestinationFolder + "/" + file.Name; 113 | FileStream stream = new FileStream(destinationFileName, FileMode.Create); 114 | BinaryWriter writer = new BinaryWriter(stream); 115 | writer.Write(binary); 116 | writer.Close(); 117 | 118 | System.Console.WriteLine("Downloaded file: {0}", destinationFileName); 119 | } 120 | clientContext.Load(folder.Folders); 121 | clientContext.ExecuteQuery(); 122 | foreach (Folder subFolder in folder.Folders) 123 | { 124 | DownloadFilesFromFolder(clientContext, subFolder, destinationFolder); 125 | } 126 | } 127 | 128 | public static byte[] getByteArray(Stream input) 129 | { 130 | byte[] buffer = new byte[16 * 1024]; 131 | using (MemoryStream ms = new MemoryStream()) 132 | { 133 | int read; 134 | while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 135 | { 136 | ms.Write(buffer, 0, read); 137 | } 138 | return ms.ToArray(); 139 | } 140 | } 141 | 142 | public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs) 143 | { 144 | // Get the subdirectories for the specified directory. 145 | DirectoryInfo dir = new DirectoryInfo(sourceDirName); 146 | 147 | if (!dir.Exists) 148 | { 149 | throw new DirectoryNotFoundException( 150 | "Source directory does not exist or could not be found: " 151 | + sourceDirName); 152 | } 153 | 154 | DirectoryInfo[] dirs = dir.GetDirectories(); 155 | // If the destination directory doesn't exist, create it. 156 | if (!Directory.Exists(destDirName)) 157 | { 158 | Directory.CreateDirectory(destDirName); 159 | } 160 | 161 | // Get the files in the directory and copy them to the new location. 162 | FileInfo[] files = dir.GetFiles(); 163 | foreach (FileInfo file in files) 164 | { 165 | string temppath = Path.Combine(destDirName, file.Name); 166 | file.CopyTo(temppath, false); 167 | } 168 | 169 | // If copying subdirectories, copy them and their contents to new location. 170 | if (copySubDirs) 171 | { 172 | foreach (DirectoryInfo subdir in dirs) 173 | { 174 | string temppath = Path.Combine(destDirName, subdir.Name); 175 | DirectoryCopy(subdir.FullName, temppath, copySubDirs); 176 | } 177 | } 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/ListsHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class ListsHelper 11 | { 12 | public static void RemoveList(ClientContext clientContext, string listDisplayName) 13 | { 14 | List oList = clientContext.Web.Lists.GetByTitle(listDisplayName); 15 | oList.DeleteObject(); 16 | try 17 | { 18 | clientContext.ExecuteQuery(); 19 | } 20 | catch (Exception) 21 | { 22 | //TODO: 23 | } 24 | } 25 | 26 | public static void GenerateListCsv(ClientContext clientContext, List oList, string fileName) 27 | { 28 | FieldCollection fieldColl = oList.Fields; 29 | clientContext.Load(fieldColl); 30 | clientContext.ExecuteQuery(); 31 | StringBuilder lines = new StringBuilder(); 32 | string headerLine = string.Join("\t", 33 | "Name", 34 | "Type", 35 | "Description", 36 | "DisplayName", 37 | "StaticName", 38 | "Group", 39 | "Hidden", 40 | "Required", 41 | "Sealed", 42 | "ShowInDisplayForm", 43 | "ShowInEditForm", 44 | "ShowInNewForm", 45 | "Guid", 46 | "Choices" 47 | ); 48 | lines.Append(headerLine + Environment.NewLine); 49 | foreach (Field fieldTemp in fieldColl) 50 | { 51 | if (fieldTemp.Hidden == false) 52 | { 53 | if (fieldTemp.ReadOnlyField == false) 54 | { 55 | if (fieldTemp.InternalName.ToString() != "ContentType") 56 | { 57 | if (fieldTemp.InternalName.ToString() != "Attachments") 58 | { 59 | System.Console.WriteLine(fieldTemp.InternalName.ToString()); 60 | 61 | string choices = string.Empty; 62 | if (fieldTemp.TypeAsString.Contains("Choice")) 63 | { 64 | var choiceField = clientContext.CastTo(fieldTemp); 65 | clientContext.Load(choiceField); 66 | clientContext.ExecuteQuery(); 67 | choices = string.Join("#", choiceField.Choices); 68 | } 69 | 70 | string fieldRow = string.Join("\t", 71 | fieldTemp.InternalName, 72 | fieldTemp.TypeAsString, 73 | fieldTemp.Description, 74 | fieldTemp.Title, 75 | fieldTemp.StaticName, 76 | fieldTemp.Group, 77 | fieldTemp.Hidden, fieldTemp.Required, fieldTemp.Sealed, 78 | "true",//ShowInDisplayForm 79 | "true",//ShowInEditForm 80 | "true",//ShowInNewForm 81 | fieldTemp.Id.ToString(), 82 | choices 83 | ); 84 | 85 | lines.Append(fieldRow + Environment.NewLine); 86 | } 87 | } 88 | } 89 | } 90 | } 91 | 92 | System.IO.Directory.CreateDirectory("Models"); 93 | System.IO.File.WriteAllText(@"Models\" + fileName, lines.ToString()); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/PasswordHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class PasswordHelper 11 | { 12 | public static SecureString GetPasswordFromConsoleInput() 13 | { 14 | ConsoleColor defaultForeground = System.Console.ForegroundColor; 15 | System.Console.ForegroundColor = ConsoleColor.Green; 16 | System.Console.WriteLine("Enter your password."); 17 | System.Console.ForegroundColor = defaultForeground; 18 | 19 | ConsoleKeyInfo info; 20 | 21 | //Get the user's password as a SecureString 22 | SecureString securePassword = new SecureString(); 23 | do 24 | { 25 | info = System.Console.ReadKey(true); 26 | System.Console.Write("*"); 27 | if (info.Key != ConsoleKey.Enter) 28 | { 29 | securePassword.AppendChar(info.KeyChar); 30 | } 31 | } 32 | while (info.Key != ConsoleKey.Enter); 33 | return securePassword; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/SPCleaner.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class SPCleaner 11 | { 12 | public static void PurgeRecycleBin(ClientContext clientContext) 13 | { 14 | SiteHelper.PurgeRecycleBin(clientContext); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/SiteHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Provision.Console.Utils 9 | { 10 | public class SiteHelper 11 | { 12 | public static void PurgeRecycleBin(ClientContext clientContext) 13 | { 14 | Site site = clientContext.Site; 15 | var recycleBinCollection = site.RecycleBin; 16 | try 17 | { 18 | clientContext.Load(site); 19 | clientContext.Load(recycleBinCollection); 20 | clientContext.ExecuteQuery(); 21 | } 22 | catch 23 | { 24 | return; 25 | } 26 | 27 | recycleBinCollection.DeleteAll(); 28 | clientContext.Load(recycleBinCollection); 29 | clientContext.ExecuteQuery(); 30 | } 31 | 32 | public static void SetSiteLogoUrl(ClientContext clientContext, string siteLogoUrl) 33 | { 34 | clientContext.Web.SiteLogoUrl = siteLogoUrl; 35 | clientContext.Web.Update(); 36 | clientContext.ExecuteQuery(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/WebPartsHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.SharePoint.Client; 2 | using Microsoft.SharePoint.Client.WebParts; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Provision.Console.Utils 10 | { 11 | public class WebPartsHelper 12 | { 13 | public static void AddCEWP(ClientContext clientContext, string formUrl, string WebPartTitle, string Zone, string contentLink, bool closeDefaultWebPart) 14 | { 15 | formUrl = formUrl.Replace("//", "/"); 16 | contentLink = contentLink.Replace("//", "/"); 17 | System.Console.WriteLine(contentLink); 18 | Microsoft.SharePoint.Client.File oFile = clientContext.Web.GetFileByServerRelativeUrl(formUrl); 19 | LimitedWebPartManager limitedWebPartManager = oFile.GetLimitedWebPartManager(PersonalizationScope.Shared); 20 | string webpartxml = @" 21 | 22 | "+ WebPartTitle + @" 23 | Default 24 | 25 | true 26 | "+ Zone + @" 27 | 0 28 | Normal 29 | 30 | 31 | true 32 | true 33 | true 34 | true 35 | true 36 | true 37 | true 38 | 39 | 40 | Modeless 41 | Default 42 | 43 | Cannot import this Web Part. 44 | /_layouts/15/images/mscontl.gif 45 | 46 | " + contentLink + @" 47 | Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c 48 | Microsoft.SharePoint.WebPartPages.ContentEditorWebPart 49 | "+ contentLink + @" 50 | 51 | 52 | " /*The webpart XML */; 53 | try 54 | { 55 | clientContext.Load(limitedWebPartManager.WebParts); 56 | clientContext.ExecuteQuery(); 57 | 58 | if (closeDefaultWebPart) 59 | { 60 | CloseDefaultWebPart(clientContext, limitedWebPartManager.WebParts); 61 | } 62 | 63 | DeleteWebPart(clientContext, formUrl, WebPartTitle); 64 | 65 | var wpd = limitedWebPartManager.ImportWebPart(webpartxml); 66 | limitedWebPartManager.AddWebPart(wpd.WebPart, Zone, 0); 67 | clientContext.ExecuteQuery(); 68 | } 69 | catch (Exception ex) 70 | { 71 | System.Console.WriteLine("error while adding the web part to the {0} form", formUrl); 72 | System.Console.WriteLine(ex.Message); 73 | } 74 | } 75 | 76 | public static void CloseDefaultWebPart(ClientContext clientContext, WebPartDefinitionCollection webPartDefinitionCollection) 77 | { 78 | foreach (var WebPart in webPartDefinitionCollection) 79 | { 80 | clientContext.Load(WebPart, w => w.WebPart.Title); 81 | 82 | clientContext.ExecuteQuery(); 83 | 84 | if (WebPart.WebPart.Title == "") 85 | { 86 | WebPart.CloseWebPart(); 87 | WebPart.SaveWebPartChanges(); 88 | clientContext.ExecuteQuery(); 89 | } 90 | } 91 | } 92 | 93 | public static void DeleteWebPart(ClientContext clientContext, string serverRelativeFormUrl, string WebPartTitle) 94 | { 95 | File oFile = clientContext.Web.GetFileByServerRelativeUrl(serverRelativeFormUrl); 96 | LimitedWebPartManager limitedWebPartManager = oFile.GetLimitedWebPartManager(PersonalizationScope.Shared); 97 | try 98 | { 99 | clientContext.Load(limitedWebPartManager.WebParts); 100 | clientContext.ExecuteQuery(); 101 | 102 | foreach (var webPart in limitedWebPartManager.WebParts) 103 | { 104 | clientContext.Load(webPart.WebPart); 105 | } 106 | clientContext.ExecuteQuery(); 107 | 108 | foreach (var WebPart in limitedWebPartManager.WebParts) 109 | { 110 | clientContext.Load(WebPart, w => w.WebPart.Title); 111 | 112 | clientContext.ExecuteQuery(); 113 | 114 | if (WebPart.WebPart.Title == WebPartTitle) 115 | { 116 | WebPart.DeleteWebPart(); 117 | clientContext.ExecuteQuery(); 118 | } 119 | } 120 | } 121 | catch (Exception ex) 122 | { 123 | System.Console.WriteLine("error while deleting the web part {0} from the form {1}", WebPartTitle, serverRelativeFormUrl); 124 | System.Console.WriteLine(ex.Message); 125 | } 126 | } 127 | 128 | public static void AddCEWPToList(ClientContext clientContext, List list) 129 | { 130 | string htmlLink = new Uri(clientContext.Web.Url).AbsolutePath + 131 | "/" + Program.AssetsLibraryInternalname + 132 | "/App/Forms/" + list.RootFolder.Name + "//" + list.RootFolder.Name + "Form.html" ; 133 | 134 | AddCEWP(clientContext, list.DefaultDisplayFormUrl, "CEWP", "Main", htmlLink, true); 135 | AddCEWP(clientContext, list.DefaultEditFormUrl, "CEWP", "Main", htmlLink, true); 136 | AddCEWP(clientContext, list.DefaultNewFormUrl, "CEWP", "Main", htmlLink, true); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/Utils/xField.cs: -------------------------------------------------------------------------------- 1 | using SPMeta2.Definitions; 2 | using SPMeta2.Definitions.Fields; 3 | using SPMeta2.Enumerations; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Provision.Console.Utils 12 | { 13 | public class xField 14 | { 15 | public string Type { get; set; } 16 | public string Name { get; set; } 17 | public string DisplayName { get; set; } 18 | public List Choices { get; set; } 19 | public string Description { get; set; } 20 | public string Group { get; set; } 21 | public Guid id { get; set; } 22 | public bool Hidden { get; set; } 23 | public bool Required { get; set; } 24 | private string AngularStringTemplate = "

{{{{f.{2}.FieldDisplayName}}}}

{3}
"; 25 | 26 | private string AngularNoteField = ""; 27 | private string AngularTextField = ""; 28 | private string AngularNumberField = ""; 29 | private string AngularTimeField = ""; 30 | private string AngularDateTimeField = ""; 31 | private string AngularBooleanField = ""; 32 | private string AngularUserField = "
"; 33 | //TODO: replace 'field' with 'ng-model' for consistency 34 | private string AngularChoiceField = " "; 35 | private string AngularRadioField = ""; 36 | 37 | public string AngularView { get; set; } 38 | 39 | public FieldDefinition definition 40 | { 41 | get 42 | { 43 | FieldDefinition fieldDefinition = null; 44 | 45 | switch (Type) 46 | { 47 | case "Text": 48 | fieldDefinition = new FieldDefinition(); 49 | fieldDefinition.FieldType = BuiltInFieldTypes.Text; 50 | 51 | AngularView = string.Format(AngularTextField,Name); 52 | break; 53 | case "Note": 54 | fieldDefinition = new FieldDefinition(); 55 | fieldDefinition.FieldType = BuiltInFieldTypes.Note; 56 | AngularView = string.Format(AngularNoteField, Name); 57 | break; 58 | 59 | case "Number": 60 | fieldDefinition = new FieldDefinition(); 61 | fieldDefinition.FieldType = BuiltInFieldTypes.Number; 62 | AngularView = string.Format(AngularNumberField, Name); 63 | break; 64 | 65 | case "Choice": 66 | ChoiceFieldDefinition choiceFieldDefinition = new ChoiceFieldDefinition(); 67 | choiceFieldDefinition.Choices = new Collection(Choices); 68 | //choiceFieldDefinition.EditFormat = "RadioButtons", 69 | choiceFieldDefinition.DefaultValue = ""; 70 | fieldDefinition = choiceFieldDefinition; 71 | AngularView = string.Format(AngularChoiceField, Name); 72 | break; 73 | 74 | case "Radio": 75 | ChoiceFieldDefinition radioFieldDefinition = new ChoiceFieldDefinition(); 76 | radioFieldDefinition.Choices = new Collection(Choices); 77 | radioFieldDefinition.EditFormat = "RadioButtons"; 78 | radioFieldDefinition.DefaultValue = ""; 79 | fieldDefinition = radioFieldDefinition; 80 | AngularView = string.Format(AngularRadioField, Name); 81 | break; 82 | 83 | case "DateTime": 84 | DateTimeFieldDefinition dateTimeFieldDefinition = new DateTimeFieldDefinition(); 85 | //dateTimeFieldDefinition.DisplayFormat = BuiltInDateTimeFieldFormatType.DateOnly, 86 | fieldDefinition = dateTimeFieldDefinition; 87 | AngularView = string.Format(AngularDateTimeField, Name); 88 | break; 89 | 90 | case "Time": 91 | DateTimeFieldDefinition TimeFieldDefinition = new DateTimeFieldDefinition(); 92 | //dateTimeFieldDefinition.DisplayFormat = BuiltInDateTimeFieldFormatType.DateOnly, 93 | fieldDefinition = TimeFieldDefinition; 94 | AngularView = string.Format(AngularTimeField, Name); 95 | break; 96 | 97 | case "User": 98 | fieldDefinition = new FieldDefinition(); 99 | fieldDefinition.FieldType = BuiltInFieldTypes.User; 100 | AngularView = string.Format(AngularUserField, Name); 101 | break; 102 | 103 | case "Boolean": 104 | fieldDefinition = new FieldDefinition(); 105 | fieldDefinition.FieldType = BuiltInFieldTypes.Boolean; 106 | AngularView = string.Format(AngularBooleanField, Name); 107 | break; 108 | 109 | default: 110 | 111 | break; 112 | } 113 | 114 | AngularView = string.Format(AngularStringTemplate, DisplayName, Type, Name, AngularView); 115 | 116 | fieldDefinition.Title = DisplayName; 117 | fieldDefinition.InternalName = Name; 118 | fieldDefinition.Id = id; 119 | fieldDefinition.Group = Group; 120 | fieldDefinition.Required = Required; 121 | 122 | return fieldDefinition; 123 | } 124 | } 125 | 126 | public xField(string[] csvColumns) 127 | { 128 | Name = csvColumns[0]; 129 | Type = csvColumns[1]; 130 | Description = csvColumns[2]; 131 | DisplayName = csvColumns[3]; 132 | Group = csvColumns[5]; 133 | Hidden = bool.Parse(csvColumns[6]); 134 | Required = bool.Parse(csvColumns[7]); 135 | id = Guid.Parse(csvColumns[12]); 136 | Choices = csvColumns[13].Split('#').ToList(); 137 | } 138 | 139 | 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /AngularForms/Provision.Console/angularJs.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/AngularForms/Provision.Console/angularJs.ico -------------------------------------------------------------------------------- /AngularForms/Provision.Console/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Deploy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/Deploy.jpg -------------------------------------------------------------------------------- /FormSample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zerg00s/AngularForms/41bb183e0a699da78a15b007c12d6beecc834afc/FormSample.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Zerg00s 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Automatically Generates AngularJs Form for any SharePoint List 2 | Works with SharePoint 2013, 2016 and SPOnline 3 | 4 | Angular View and Controller are automatically generated and applied to the target SharePoint list of your choice. 5 | ### Warning: 6 | Disable [Minimal Download Strategy](http://www.sharepointdiary.com/2015/02/disable-minimal-download-strategy-mds-in-sharepoint-2013.html) site feature. Otherwise Angular form will not render properly. 7 | 8 | ![Form Sample](https://github.com/Zerg00s/AngularForms/blob/master/FormSample.jpg?raw=true) 9 | 10 | ## How to Deploy Angular Forms: 11 | - Download the latest release as a ZIP-archive [from here](https://github.com/Zerg00s/AngularForms/raw/master/AngularForms/Provision.Console/Releases/Release%20package.zip) 12 | - Extract the folder and run .EXE file 13 | - Specify the full URL of the site with the existing list 14 | - Enter your login 15 | - Enter Passowrd 16 | - Enter list display name. For example, Courses 17 | - Angular view and controller will be automatically generated based on the list you selected 18 | 19 | 20 | 21 | ![Deploy sample](https://github.com/Zerg00s/AngularForms/blob/master/AngularForms.gif?raw=true) 22 | 23 | 24 | ## How to modify the form 25 | Assuming you are not familiar with modern tools like [SPGO](https://marketplace.visualstudio.com/items?itemName=SiteGo.spgo) or [SPPP](https://github.com/koltyakov/generator-sppp), I will just suggest mapping the /Assets/App folder using WebDav. First Open it in Internet Explorer for authentication purposes. Open it in Visual Studio Code. 26 | Angular views and controllers will be deployed in the /Assets/App/Forms/Your_List_Name/ folder. 27 | 28 | You will have to know your field internal names to be able to refer them. 29 | From the controller you refer to the fields like so: $scope.f.fieldName.Value. 30 | From the View you refer to the fields like so: {{f.fieldName.Value}} or ng-model="f.fieldName.Value" 31 | 32 | The generated Angular form is just a scaffolding and is meant to be modified according to your business logic. You will probably want to add ng-required, ng-hidden, et. to your fields 33 | 34 | Saving and loading happens automatically. Not all field types are available. Refer to the bottom section for the full list. 35 | 36 | Missing field types: 37 | - multichoice 38 | - lookup/multilookup 39 | - taxonomy 40 | 41 | Feel free to contribute to the Angular service spFormFactory.js to include support for the missing field types 42 | 43 | ## Available field types: 44 | ``` 45 | 46 |
47 |

{{f.Requestor.FieldDisplayName}}

48 |
49 |
50 | 51 | 52 |
53 |

{{f.StartDate.FieldDisplayName}}

54 | 55 |
56 | 57 | 58 |
59 |

Time

60 | 61 | {{f.StartTime.FieldDisplayName}} 62 | 63 |
64 |
65 | 66 | 67 |
68 |

Duration

69 | 70 |
71 | 72 | 73 |
74 |

{{f.WithPay.FieldDisplayName}}

75 | 76 |
77 | 78 | 79 |
80 |

Option

81 | 84 |
85 | 86 | 87 | 88 | 89 | 90 |
91 |

Price

92 | 93 |
94 | 95 | 96 |
97 |

{{f.PhoneNumber.FieldDisplayName}}

98 | 99 |
100 | 101 | 102 |
103 |

{{f.Comments.FieldDisplayName}}

104 | 105 |
106 | 107 | 108 |
109 |

Documents:

110 | 113 | 114 | 115 | 116 | 117 |
118 | ``` 119 | --------------------------------------------------------------------------------