Compare commits

...

207 Commits

Author SHA1 Message Date
kgiszewski e9da0aa351 What a mess this is turing out to be 👎 2015-08-18 12:09:16 -04:00
kgiszewski b42e411e49 Add MinFieldsets to the prevalue model 2015-08-17 16:09:53 -04:00
kgiszewski 4c4b09b187 Init 2015-08-17 16:04:41 -04:00
kgiszewski 43a72ed5e5 Use relative paths instead of tilde due to core compatibility issues 2015-08-17 12:16:38 -04:00
kgiszewski 709198f943 Merge branch 'master' of github.com:imulus/Archetype 2015-08-17 11:53:44 -04:00
Kevin Giszewski 77f72ed72e Merge pull request #283 from kipusoep/master
Fixes for Virtual Directories #156
2015-08-17 11:47:52 -04:00
kgiszewski a03fe3af32 Remove some cruft 2015-08-17 11:47:08 -04:00
Stefan Kip 697a797c7e Fixes for Virtual Directories #156 2015-08-14 14:49:41 +02:00
kgiszewski cfe014ee45 Bump version number 2015-07-08 13:26:06 -04:00
kgiszewski d62fa05ab5 Handle 7.2.6 issue 2015-07-01 09:25:18 -04:00
kjac 662cf4c3bf More formatting 2015-06-26 14:17:52 +02:00
kjac d0b8314134 Formatting issue 2015-06-26 14:09:12 +02:00
kjac 8eb4786976 Revert API method GetByGuid() to its previous state
All default prevalue enrichment is now handled by the API method
GetAllPropertyEditors()
2015-06-26 14:08:00 +02:00
kjac 20155b5ca6 Move filenames collection to temporary editor state container 2015-06-26 11:30:51 +02:00
kjac 16c310f3c6 Ensure correct default prevalues for imagecropper 2015-06-26 11:27:54 +02:00
kjac 99d570dc97 Handle upload and image cropper clientside 2015-06-25 07:59:16 +02:00
kjac 2ae3e3ade9 Merge with imulus/master 2015-06-23 17:21:26 +02:00
Kevin Giszewski d4718e358c Merge pull request #279 from leekelleher/enhancement/helper-log-exception
ArchetypeHelper - added exception to Umbraco log
2015-06-18 08:05:10 -04:00
Kevin Giszewski bb91eb7036 Merge pull request #280 from leekelleher/upgrade/courier-assemblies
Upgraded Courier assemblies.
2015-06-18 08:03:58 -04:00
leekelleher 484f2c22a3 Added exception to Umbraco log, as VS was complaining about an unused ex. 2015-06-18 12:20:02 +01:00
leekelleher a2121cd8a7 Upgraded Courier assemblies.
Amended references to Courier constants (seems that there was some restructuring within Courier)
2015-06-18 12:17:44 +01:00
kgiszewski 2fb922fd6c Rework dropdown label to check for a value first 2015-06-15 15:56:45 -04:00
kgiszewski c2986d39a9 Added coreDropdown to label helpers 2015-06-15 15:46:51 -04:00
kgiszewski 8ee5488261 Merge branch 'master' of github.com:imulus/Archetype 2015-06-15 14:49:19 -04:00
kgiszewski c60c9e1c5d Fix #276 2015-06-15 14:48:50 -04:00
kgiszewski 8610f69c88 Bump version to v1.8 2015-06-04 13:26:19 -04:00
kgiszewski 34b4209de7 For some reason sorting the RTE reared its head again and I killed it (again). 2015-06-02 10:49:47 -04:00
Kevin Giszewski b6145c9275 Merge pull request #275 from imulus/feature/label-library
Allow args to be passed to label templates and begin label library
2015-06-01 13:54:43 -04:00
kgiszewski f51ca65659 Expose archetypePropertyEditorResource to controller 2015-06-01 13:53:18 -04:00
kgiszewski d026af9fd2 Expose archetypeCacheService on controller 2015-06-01 13:49:34 -04:00
kgiszewski 11fff5da1a Add media picker support 2015-06-01 13:43:42 -04:00
kgiszewski 788a5dd720 Wire up MNTP 2015-06-01 13:35:53 -04:00
kgiszewski 24e232b2cc Renaming binge 2015-06-01 12:12:33 -04:00
kgiszewski 5bdcb23933 Cache datatypes as they come back from server 2015-06-01 11:16:12 -04:00
kgiszewski 34b3ed3b47 Add archetypeCacheService 2015-06-01 10:13:29 -04:00
kgiszewski 50a486a9ac Discovered we should probably use a datatype cache based on the directive, so maybe a archetypeCacheService? 2015-06-01 10:09:22 -04:00
kgiszewski 4f4128a744 Fix some broken-ness 2015-06-01 10:02:32 -04:00
kgiszewski 4851797a83 Refactor a ton of things, add archetypeLabelService 2015-06-01 09:45:10 -04:00
kgiszewski 54a435dce7 Begin archetypeService 2015-05-29 08:55:08 -04:00
kgiszewski 03a170d716 Add RTE label template 2015-05-27 13:56:33 -04:00
kgiszewski 37976abc84 Handle arg detection better and change UrlPicker functionname 2015-05-27 13:47:23 -04:00
kgiszewski f7e96438be Handle null ref 2015-05-27 13:41:58 -04:00
kgiszewski f1c3caae2d Allow args to be passed to label templates and begin label library 2015-05-27 13:31:25 -04:00
kgiszewski 8f8078e12f Merge branch 'master' into pr/272 2015-05-26 08:33:34 -04:00
kgiszewski dbc9b872d8 Fix #274 2015-05-26 08:28:32 -04:00
Nicholas-Westby eef1b94586 Hide long fieldset headers with an ellipsis before overlapping buttons: https://github.com/imulus/Archetype/issues/271 2015-05-23 00:01:25 -07:00
kgiszewski 9bbf366fe2 Bump version to v1.7.5 2015-05-11 15:32:46 -04:00
kgiszewski 368a9f6c07 Fix for #268 2015-05-11 15:31:46 -04:00
kgiszewski d3b3f80f3d Add Umbraco as a dependency 2015-05-11 15:20:28 -04:00
kgiszewski 11f7881dd7 Merge branch 'master' of github.com:imulus/Archetype 2015-05-04 13:46:07 -04:00
kgiszewski 9894357469 Fix #268 (This is a temp fix until a better solution can be found) 2015-05-04 13:45:49 -04:00
kgiszewski 146a3770a1 Bump version to v1.7.4 2015-05-03 16:41:41 -04:00
kgiszewski caf9d1ac15 Fix grunt for debug 2015-04-29 08:53:18 -04:00
kgiszewski 614595ceb3 Finesse PR #269 2015-04-29 08:53:05 -04:00
kgiszewski d1b21a1ca7 Merge branch 'pr/269' 2015-04-29 08:13:40 -04:00
kgiszewski 54bc507049 Merge branch 'pr/267' 2015-04-29 08:12:56 -04:00
kgiszewski 037585458c Merge branch 'pr/266' 2015-04-29 08:12:15 -04:00
kgiszewski f52649eb9e Add Courier to the build process for distro 2015-04-29 08:08:08 -04:00
kgiszewski 423fedb954 Undo add Courier to distro per @leekelleher 's suggestion that it causes a ysod if Courier is not installed already 2015-04-29 07:46:37 -04:00
Kim Pilgaard b39312ccd2 Properties which no longer exist have no GUID. Remove these when reading and writing the data. 2015-04-29 08:56:17 +02:00
Gavin Faux b9c4be0bb6 PropertyEditorAlias null check
Don't try `PropertyValueConverters` for properties with null or empty
`PropertyEditorAlias`, prevents `System.NullReferenceException`  in
`PropertyValueConverter.IsConverter` implementations
2015-04-28 14:30:08 +01:00
Tom Van Rompaey 29285607a9 Small UX update for add button
Added class "archetypeAddButton" to the button so it can make use of the
CSS that is writen for it.
The button should also have a cursor: pointer on hover.
2015-04-25 16:16:04 +02:00
kgiszewski 909b87cea0 Add Courier dll to the distribution 2015-04-21 08:43:44 -04:00
kgiszewski 3d25f75fb9 Bump version number to v1.7.3 2015-04-16 08:54:36 -04:00
kgiszewski 6fa713f88e Change to the internal event 2015-04-15 15:32:08 -04:00
kgiszewski d9982fe3a2 Merge branch 'master' of github.com:imulus/Archetype 2015-04-15 15:30:11 -04:00
kgiszewski 588bdfe429 Update to Tom's latest packager 2015-04-15 15:30:03 -04:00
Kevin Giszewski 0174f6d78b Merge pull request #262 from kjac/submit-watcher
Fix #261
2015-04-15 15:29:33 -04:00
Kevin Giszewski 84144b6206 Update Readme 2015-04-10 11:27:11 -04:00
kjac 27910e8d22 Fix #261
Add a watch to the "formSubmitting" event for each property added to a
fieldset, to make sure Archetype gets the last say in the
"formSubmitting" event.
2015-04-04 21:57:49 +02:00
Tom Fulton 9bf413207f Fix logic issue with assemblyinfo patcher 2015-04-02 23:24:54 -06:00
kgiszewski e5cd3d0cb0 Bump Version to 1.7.2 2015-03-31 11:04:57 -04:00
leekelleher 032ee958c1 Minor whitespace formatting 2015-03-27 15:48:14 +00:00
Kevin Giszewski ef5bd7ccc8 Merge pull request #259 from sitereactor/master
Updates the Courier provider
2015-03-24 13:51:47 -04:00
Morten Christensen 7839e4a992 Updates the Courier provider to only use Courier code instead of relying on PropertyEditorConverters 2015-03-24 16:11:19 +01:00
kgiszewski 408c178348 Fix #194 2015-03-13 10:18:57 -04:00
kgiszewski 852b7a92a7 Update for v7.2.2 locale issue 2015-02-26 10:37:27 -05:00
kgiszewski 5a4118a1cc Bump version and fix clone issue 2015-01-27 11:05:43 -05:00
kgiszewski 4b603bf97f Bump Version Number 2015-01-27 10:53:17 -05:00
kgiszewski c8884c8d92 Add Cloning 2015-01-27 10:51:22 -05:00
kgiszewski dd843ce2c6 Make deep requests not the default 2015-01-27 10:01:59 -05:00
kgiszewski 8036ab72d0 Merge branch 'alt-label-template' 2015-01-27 09:44:36 -05:00
kgiszewski b25d8bdc4b Merge branch 'fix/datatype-caching' 2015-01-27 09:42:36 -05:00
Nicholas-Westby 023d99cc88 Improved performance of publish operations: https://github.com/imulus/Archetype/issues/238 2015-01-26 12:59:19 -08:00
kjac 1cc0586c75 Support alternative property in label template
Allow fieldset label templates to contain alternative/fallback property
aliases and/or functions by seperating with "|" - e.g.
{{title|myFunction(text)}}
2015-01-10 11:16:00 +01:00
kjac a16b61f03f Merge remote-tracking branch 'upstream/master' 2015-01-10 08:26:41 +01:00
Tom Fulton 7ea01cad86 Remove caching for property datatype dropdowns 2014-12-03 21:46:13 -07:00
Mads Krohn aea65a531d Tweak dropdown position for new fields
See related issue
2014-11-02 12:56:12 +01:00
Kevin Giszewski 482cb5a149 beta = gtfo 2014-11-02 12:56:12 +01:00
Kevin Giszewski 81ac5fbddb Update lang files 2014-11-02 12:56:11 +01:00
Kevin Giszewski 801baf355b Bump version number to v1.6 2014-11-02 12:56:10 +01:00
Kevin Giszewski a3b531caa4 Tidy up the PR 2014-11-02 12:56:10 +01:00
doronuziel71 1d680c612e Fixed type-o 2014-11-02 12:56:09 +01:00
doronuziel71 cdea3c1aec Fixed type-o 2014-11-02 12:56:09 +01:00
doronuziel71 37fa9c40d6 Introduced override default propety converter 2014-11-02 12:56:08 +01:00
Kevin Giszewski 774ba46e13 Flip-flop scope and fieldset 2014-11-02 12:56:07 +01:00
Kevin Giszewski 280a97c8d1 Expose FS (fieldsets) and Property (alias/value) for helping with creating Archetype from code 2014-11-02 12:56:07 +01:00
Kevin Giszewski 7dd3848bdf Expose serializer for those wanting to create Archetypes from code 2014-11-02 12:56:06 +01:00
leekelleher add44e533a Courier: Turns out that creating a new instance of PropertyItemProvider was a hack.
Replaced with getting the item-provider from the existing collection.
2014-11-02 12:56:05 +01:00
leekelleher 870b848e3b Bug fix with the Courier resolver 2014-11-02 12:56:05 +01:00
leekelleher b262d8a86f Set the project's assembly references to not "Copy Local".
As these pollute the /bin output folder during build.
2014-11-02 12:56:04 +01:00
leekelleher 5dba1a0895 Fixed the type-name for the error log messages 2014-11-02 12:56:03 +01:00
leekelleher 8f4857aba1 Fixed issue with Courier serialization.
When Courier was deserializing, it was treating any nested Archetype as a `JObject`.
The newer serializer routines in Archetype core resolve the previous issue.
2014-11-02 12:56:03 +01:00
leekelleher cd95404a08 PersistenceManager.Default was obsoleted, replaced calls with ExecutionContext.DatabasePersistence 2014-11-02 12:56:02 +01:00
leekelleher 7e7a4aff58 Upgraded Courier assemblies. 2014-11-02 12:56:01 +01:00
Mads Krohn c9d8952b7f Tweak dropdown position for new fields
See related issue
2014-10-02 14:46:26 +02:00
Kevin Giszewski 890b5674a6 beta = gtfo 2014-09-26 09:27:31 -04:00
Kevin Giszewski 7f5dbd31c9 Update lang files 2014-09-26 09:13:31 -04:00
Kevin Giszewski a2255aa037 Bump version number to v1.6 2014-09-25 14:27:52 -04:00
Kevin Giszewski 415a84f5c0 Tidy up the PR 2014-09-25 14:21:16 -04:00
doronuziel71 3a0eba401a Fixed type-o 2014-09-17 19:18:47 +03:00
doronuziel71 991d56dac1 Fixed type-o 2014-09-17 19:17:58 +03:00
doronuziel71 f704088bcb Merge remote-tracking branch 'upstream/master' 2014-09-17 18:37:00 +03:00
doronuziel71 a599215620 Introduced override default propety converter 2014-09-16 23:32:16 +03:00
Kevin Giszewski a6e76cb398 Flip-flop scope and fieldset 2014-09-16 13:55:54 -04:00
Kevin Giszewski 4fd134ac74 Expose FS (fieldsets) and Property (alias/value) for helping with creating Archetype from code 2014-09-08 10:39:13 -04:00
Kevin Giszewski 22b87c0a37 Merge branch 'develop' of github.com:imulus/Archetype into develop 2014-09-08 10:00:28 -04:00
Kevin Giszewski d707b55362 Expose serializer for those wanting to create Archetypes from code 2014-09-08 10:00:05 -04:00
Kevin Giszewski 37a195109c Merge pull request #220 from leekelleher/feature/courier-upgrade
Courier: Fix for PropertyItemProvider reference
2014-09-04 08:52:10 -04:00
leekelleher 205919ccae Courier: Turns out that creating a new instance of PropertyItemProvider was a hack.
Replaced with getting the item-provider from the existing collection.
2014-09-04 11:05:41 +01:00
leekelleher 04e57b7d6b Bug fix with the Courier resolver 2014-09-02 16:52:41 +01:00
Kevin Giszewski 9e8cc0c556 Merge pull request #218 from leekelleher/feature/courier-upgrade
Bug fix with the Courier resolver
2014-09-02 11:52:27 -04:00
Kevin Giszewski 8fe90c3b86 Merge pull request #216 from leekelleher/feature/courier-upgrade
Courier upgrade (UaaS)
2014-09-02 08:58:20 -04:00
Kevin Giszewski 99581b0aeb Merge pull request #217 from leekelleher/develop
Housekeeping
2014-09-02 08:57:35 -04:00
leekelleher d8939c59a0 Set the project's assembly references to not "Copy Local".
As these pollute the /bin output folder during build.
2014-09-02 13:30:21 +01:00
leekelleher e49fe6ee17 Fixed the type-name for the error log messages 2014-09-02 13:27:29 +01:00
leekelleher ca52f0a216 Fixed issue with Courier serialization.
When Courier was deserializing, it was treating any nested Archetype as a `JObject`.
The newer serializer routines in Archetype core resolve the previous issue.
2014-09-02 13:24:40 +01:00
leekelleher 08d4e4b51d PersistenceManager.Default was obsoleted, replaced calls with ExecutionContext.DatabasePersistence 2014-09-02 13:20:29 +01:00
leekelleher e9c51ee96e Upgraded Courier assemblies. 2014-09-02 13:20:15 +01:00
Kevin Giszewski b5f281cae0 Prefix property aliases to avoid core css conflicts (BREAKING) 2014-08-26 10:43:37 -04:00
Kevin Giszewski 3bbb27f85e Fix error state LESS and other stuffs 2014-08-26 10:43:13 -04:00
Kevin Giszewski 247eea3477 Merge branch 'develop' 2014-08-26 10:05:18 -04:00
Kevin Giszewski 8635fa7301 Cleanup the LESS even if a little 2014-08-26 10:05:02 -04:00
Rasmus John Pedersen e49a8d947d fixed bug with custom view 2014-08-22 10:46:45 +02:00
Kevin Giszewski 3e2e43d342 Update langs and bump version number 2014-08-21 13:00:52 -04:00
Jeavon Leopold 78ba99a52e Change Archetype value conversion attempt to pass in the Source value to ConvertSourceToObject instead of the Data value 2014-08-18 17:14:17 +01:00
Kevin Giszewski 42efa1a3d4 Merge branch 'pr/200'
Conflicts:
	app/directives/archetypeproperty.js
2014-08-18 09:43:06 -04:00
Kevin Giszewski d2f4fce808 Add enable deep requests 2014-08-18 08:55:13 -04:00
Kevin Giszewski d76a5f58d4 Merge branch 'develop' 2014-08-13 11:29:12 -04:00
Kevin Giszewski f6457416cc Make sort icon black
- WS cleanup
2014-08-13 11:28:57 -04:00
Kevin Giszewski c841813a74 decouple entityResource from the function call 2014-08-13 11:15:29 -04:00
Kevin Giszewski bcc7be94e7 fix typo 2014-08-13 11:05:27 -04:00
Kevin Giszewski e200c22244 More caching 2014-08-12 19:15:08 -04:00
Kevin Giszewski 244db7f19d Add caching to $http.gets 2014-08-12 19:04:20 -04:00
Kevin Giszewski 31f3d00b76 Add label helpers 2014-08-12 17:15:16 -04:00
Kevin Giszewski 07125bae84 Add ability to pass function as template 2014-08-12 16:56:23 -04:00
kjac f2a8286f00 Fix #131 again
Simplified the validation and fixed the problem mentioned in #131 with
only the last field in a fieldset being validated.
2014-08-11 19:12:38 +02:00
Kevin Giszewski 5725c0770e Bump version number to v1.4.1 2014-08-06 09:22:08 -04:00
Kevin Giszewski 210fbb8230 Fix for #158 2014-08-06 09:20:17 -04:00
Kevin Giszewski c8e398c726 Merge pull request #195 from imulus/feature/fix193
Fix for #193
2014-08-06 08:55:47 -04:00
Kevin Giszewski bfa882fa01 Fix for #193 2014-08-06 08:55:10 -04:00
Kevin Giszewski 876aea4007 Merge branch 'pr/186' into develop 2014-08-06 08:45:55 -04:00
Jeroen Breuer 07750c7537 Run ConvertDataToSource before ConvertSourceToObject 2014-08-05 13:17:34 +02:00
Kevin Giszewski 17a1577d09 Merge branch 'master' of github.com:imulus/Archetype 2014-07-31 13:55:07 -04:00
Kevin Giszewski 987f383139 Merge pull request #184 from imulus/fix/class-conflicts
Prefix fieldset class names to help avoid conflicts
2014-07-31 13:54:58 -04:00
Kevin Giszewski dc14f11f83 Merge pull request #191 from jbreuer/patch-5
Fix 4 for #187
2014-07-31 13:54:48 -04:00
Kevin Giszewski 500f4c4dee Merge pull request #190 from jbreuer/patch-4
Fix 3 for #187
2014-07-31 13:53:41 -04:00
Kevin Giszewski a16451df1f Merge pull request #189 from jbreuer/patch-3
Fix 2 for #187
2014-07-31 13:53:34 -04:00
Kevin Giszewski 9ac7877174 Merge pull request #188 from jbreuer/patch-2
Fix 1 for #187
2014-07-31 13:53:10 -04:00
Kevin Giszewski 4d3bcb68b3 Merge branch 'pr/188' into develop 2014-07-31 13:44:43 -04:00
Kevin Giszewski 30074fe198 Merge branch 'pr/191' into pr/188 2014-07-31 13:37:01 -04:00
Kevin Giszewski 7f0bd45a9d Merge branch 'pr/190' into pr/188 2014-07-31 13:36:59 -04:00
Kevin Giszewski 6045eed5c5 Merge branch 'pr/189' into pr/188 2014-07-31 13:36:55 -04:00
Jeroen Breuer 57ffa69ff5 Added node id 2014-07-31 12:12:35 +02:00
Jeroen Breuer 6b61dc978a Added node id 2014-07-31 12:11:51 +02:00
Jeroen Breuer c20aa64af2 Added node id 2014-07-31 12:11:02 +02:00
Jeroen Breuer 25826958a3 Fix 4 for #187 2014-07-30 16:34:33 +02:00
Jeroen Breuer b5bfbb5c25 Fix 3 for #187 2014-07-30 16:33:01 +02:00
Jeroen Breuer 9afaa024c0 Fix 2 for #187 2014-07-30 16:30:42 +02:00
Jeroen Breuer c58dcd80ff Fix 1 for #187 2014-07-30 16:26:42 +02:00
Jeroen Breuer b7c16ee6ef Fix for #185 2014-07-29 16:24:14 +02:00
tomfulton 786c547e0b Prefix fieldset class names to help avoid conflicts 2014-07-24 06:35:33 -06:00
Kevin Giszewski fbf686f559 Bump Version Number to v1.4.0 2014-07-11 10:38:08 -04:00
Kevin Giszewski 42b4076700 Merge branch 'pr/174' 2014-07-11 10:19:00 -04:00
Kevin Giszewski 5feb415093 Update some dropdown css 2014-07-11 10:17:49 -04:00
Kevin Giszewski 79c85cf86b Merge branch 'master' into pr/174 2014-07-09 16:42:18 -04:00
Kevin Giszewski a0f65370c9 Few CSS tweaks 2014-07-09 16:40:29 -04:00
Kevin Giszewski 029d17c428 Merge branch 'master' of github.com:imulus/Archetype 2014-07-09 15:46:17 -04:00
Kevin Giszewski e262d7b0c9 Re-fix the 'hide label' issue
- appears to have been undone
2014-07-09 15:46:05 -04:00
kjac 44ea6c56f5 Use propertyAlias in fieldset validation
As described in #162 the umbracoPropertyAlias has been removed in favor
of a more unique propertyAlias. This propertyAlias should be used for
property identification in the validation.
2014-07-01 22:28:20 +02:00
leekelleher d7477eaf6d Moved the ArchetypePropertyModel.CreateDummyPropertyType to an extension method.
With a view to re-use in the Courier DataResolver (as it does the same function).
2014-07-01 21:46:25 +02:00
leekelleher c33649201f Separated out the extension methods into their own grouped classes.
Implements #172
2014-07-01 21:46:25 +02:00
leekelleher 3940955360 Code tidy-up; correct method naming; removed unused references 2014-07-01 21:46:24 +02:00
leekelleher 03f66a35f7 Refactored the DataResolver, as the underlying JSON value for the property had been modified (fields removed). 2014-07-01 21:46:24 +02:00
leekelleher b4b60dd89c Add the 'Archetype.Courier' project.
Includes the Courier DataResolver for Archetype.
2014-07-01 21:46:23 +02:00
leekelleher 4105912394 Code tidy-up: removed the "Models" namespace from the type name. 2014-07-01 21:46:22 +02:00
Kevin Giszewski 7b3d31f897 Merge pull request #173 from leekelleher/feature/issues/172
Separated out the extension methods into their own grouped classes
2014-07-01 11:52:43 -04:00
leekelleher 50861badf1 Moved the ArchetypePropertyModel.CreateDummyPropertyType to an extension method.
With a view to re-use in the Courier DataResolver (as it does the same function).
2014-07-01 16:49:20 +01:00
leekelleher fa682c3717 Separated out the extension methods into their own grouped classes.
Implements #172
2014-07-01 16:48:13 +01:00
Kevin Giszewski d18d1ff0b1 Merge pull request #171 from leekelleher/feature/courier-resolver
Includes Courier DataResolver project
2014-07-01 11:27:21 -04:00
leekelleher 247491187a Code tidy-up; correct method naming; removed unused references 2014-07-01 16:09:34 +01:00
leekelleher 80194786a1 Refactored the DataResolver, as the underlying JSON value for the property had been modified (fields removed). 2014-07-01 15:42:41 +01:00
Kevin Giszewski 72ee7b3d09 Merge pull request #170 from leekelleher/master
Code tidy-up: removed the "Models" namespace from the type name.
2014-07-01 10:20:18 -04:00
leekelleher 284b1d93dc Add the 'Archetype.Courier' project.
Includes the Courier DataResolver for Archetype.
2014-07-01 14:28:02 +01:00
leekelleher 7c5a3c34e2 Code tidy-up: removed the "Models" namespace from the type name. 2014-07-01 13:54:18 +01:00
Kevin Giszewski fa970750d1 Bump version number to v.1.3.1-beta 2014-06-30 11:22:34 -04:00
Kevin Giszewski aeeb3c7b40 Remove Serialization 2014-06-30 11:22:21 -04:00
kjac 1cbb7b3173 Merge with master 2014-06-16 16:57:51 +02:00
kjac 71be453ada Move property files collection clean-up
Moved the cleaning up of files selected for each property to the
SerializeForPersistence() method
2014-06-01 07:48:47 +02:00
kjac efae05b3ae Merge branch 'master' into upload-imagecrop-datatypes 2014-05-29 11:17:11 +02:00
kjac 84acd43ccf Enrich datatypes with default prevalues
Datatypes can have default prevalues, that are not saved as part of the
config and thus need to be added when loading the datatype - e.g. the
"focalPoint" prevalue for the image cropper datatype.
2014-05-29 11:14:45 +02:00
kjac 9fe756bacb Merge branch 'master' into upload-imagecrop-datatypes 2014-05-21 23:01:44 +02:00
kjac cd03b5a4f9 Test and fine tune 3rd level nested archetypes 2014-05-20 22:19:21 +02:00
kjac 07a62d7edf More file upload handling WIP 2014-05-20 21:28:29 +02:00
kjac a6c166d926 WIP handle file selection
Use FileManager to register the files selected for properties contained
within an Archetype
2014-05-18 18:19:20 +02:00
kjac c1bc555443 Merge branch 'master' into current-value-to-value-editor 2014-05-16 13:44:46 +02:00
kjac d4166f33e8 Correct currentValue for ValueEditor conversion
Ensure that the currentValue parameter sent to the fieldset property
ValueEditor ConvertEditorToDb() method contains the value that was
previously entered (if any) and not the one that was just entered.
2014-05-14 11:32:54 +02:00
92 changed files with 2312 additions and 4346 deletions
+13 -8
View File
@@ -55,10 +55,15 @@ module.exports = function(grunt) {
'app/controllers/controller.js',
'app/controllers/config.controller.js',
'app/directives/archetypeproperty.js',
'app/directives/archetypesubmitwatcher.js',
'app/directives/archetypecustomview.js',
'app/directives/localize.js',
'app/services/localization.js',
'app/resources/propertyeditor.js'
'app/directives/archetypeLocalize.js',
'app/services/archetypeLocalizationService.js',
'app/helpers/sampleLabelHelpers.js',
'app/resources/archetypePropertyEditorResource.js',
'app/services/archetypeService.js',
'app/services/archetypeLabelService.js',
'app/services/archetypeCacheService.js'
],
dest: '<%= basePath %>/js/archetype.js'
}
@@ -72,7 +77,7 @@ module.exports = function(grunt) {
expand: true
},
dll: {
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Release/',
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Debug/',
src: 'Archetype.dll',
dest: '<%= dest %>/bin/',
expand: true
@@ -162,10 +167,10 @@ module.exports = function(grunt) {
assemblyinfo: {
options: {
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj'],
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj', 'app/Umbraco/Umbraco.Archetype/Archetype.Courier.csproj'],
filename: 'VersionInfo.cs',
info: {
version: '<%= (pkgMeta.version.indexOf("-") ? pkgMeta.version.substring(0, pkgMeta.version.indexOf("-")) : pkgMeta.version) %>',
version: '<%= (pkgMeta.version.indexOf("-") > 0 ? pkgMeta.version.substring(0, pkgMeta.version.indexOf("-")) : pkgMeta.version) %>',
fileVersion: '<%= pkgMeta.version %>'
}
}
@@ -198,9 +203,9 @@ module.exports = function(grunt) {
}
},
dist: {
src: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj'],
src: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj','app/Umbraco/Archetype.Courier/Archetype.Courier.csproj'],
options: {
projectConfiguration: 'Release',
projectConfiguration: 'Debug',
targets: ['Clean', 'Rebuild'],
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ Install the selected <a href='https://github.com/imulus/Archetype/releases'>rele
## Official Docs ##
http://imulus.github.io/Archetype
https://github.com/kgiszewski/ArchetypeManual
Follow us on Twitter https://twitter.com/ArchetypeKit
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FE8BE437-8B11-4E49-9B02-F45994E6D723}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Archetype.Courier</RootNamespace>
<AssemblyName>Archetype.Courier</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="businesslogic">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\businesslogic.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="cms">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\cms.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="interfaces">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="log4net">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\log4net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Xml" />
<Reference Include="umbraco">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Core">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Courier.Core">
<HintPath>lib\Umbraco.Courier.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Courier.DataResolvers">
<HintPath>lib\Umbraco.Courier.DataResolvers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Courier.Providers">
<HintPath>lib\Umbraco.Courier.Providers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.providers">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.providers.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Umbraco.Archetype\Properties\VersionInfo.cs">
<Link>Properties\VersionInfo.cs</Link>
</Compile>
<Compile Include="DataResolvers\ArchetypeDataResolver.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Archetype\Archetype.Umbraco.csproj">
<Project>{7d185d41-4228-4978-acb8-83f9a48ad94f}</Project>
<Name>Archetype.Umbraco</Name>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Extensions;
using Archetype.Models;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Courier.Core;
using Umbraco.Courier.Core.Logging;
using Umbraco.Courier.Core.ProviderModel;
using Umbraco.Courier.DataResolvers;
using Umbraco.Courier.ItemProviders;
namespace Archetype.Courier.DataResolvers
{
public class ArchetypeDataResolver : PropertyDataResolverProvider
{
private enum Direction
{
Extracting,
Packaging
}
public override string EditorAlias
{
get
{
return Constants.PropertyEditorAlias;
}
}
public override void ExtractingDataType(DataType item)
{
// No longer need to extract the DataType (int) Ids as Archetype now references the Guid [LK]
}
public override void ExtractingProperty(Item item, ContentProperty propertyData)
{
ReplacePropertyDataIds(item, propertyData, Direction.Extracting);
}
public override void PackagingDataType(DataType item)
{
AddDataTypeDependencies(item);
}
public override void PackagingProperty(Item item, ContentProperty propertyData)
{
ReplacePropertyDataIds(item, propertyData, Direction.Packaging);
}
private void AddDataTypeDependencies(DataType item)
{
if (item.Prevalues != null && item.Prevalues.Count > 0)
{
var prevalue = item.Prevalues[0];
if (prevalue.Alias.InvariantEquals(Constants.PreValueAlias) && !string.IsNullOrWhiteSpace(prevalue.Value))
{
var config = JsonConvert.DeserializeObject<ArchetypePreValue>(prevalue.Value);
if (config != null && config.Fieldsets != null)
{
foreach (var property in config.Fieldsets.SelectMany(x => x.Properties))
{
item.Dependencies.Add(property.DataTypeGuid.ToString(), ItemProviderIds.dataTypeItemProviderGuid);
}
item.Prevalues[0].Value = JsonConvert.SerializeObject(config, Formatting.None);
}
}
}
}
private void ReplacePropertyDataIds(Item item, ContentProperty propertyData, Direction direction)
{
if (propertyData != null && propertyData.Value != null)
{
var dataType = ExecutionContext.DatabasePersistence.RetrieveItem<DataType>(new ItemIdentifier(propertyData.DataType.ToString(),
ItemProviderIds.dataTypeItemProviderGuid));
//Fetch the Prevalues for the current Property's DataType (if its an 'Archetype config')
var prevalue = dataType.Prevalues.FirstOrDefault(x => x.Alias.ToLowerInvariant().Equals("archetypeconfig"));
var archetypePreValue = prevalue == null
? null
: JsonConvert.DeserializeObject<ArchetypePreValue>(prevalue.Value,
ArchetypeHelper.Instance.JsonSerializerSettings);
RetrieveAdditionalProperties(ref archetypePreValue);
//Deserialize the value of the current Property to an ArchetypeModel and set additional properties before converting values
var sourceJson = propertyData.Value.ToString();
var archetype = JsonConvert.DeserializeObject<ArchetypeModel>(sourceJson, ArchetypeHelper.Instance.JsonSerializerSettings);
RetrieveAdditionalProperties(ref archetype, archetypePreValue);
if (archetype != null)
{
// get the `PropertyItemProvider` from the collection.
var propertyItemProvider = ItemProviderCollection.Instance.GetProvider(ItemProviderIds.propertyDataItemProviderGuid, ExecutionContext);
foreach (var property in archetype.Fieldsets.SelectMany(x => x.Properties))
{
if (property == null || string.IsNullOrWhiteSpace(property.PropertyEditorAlias))
continue;
// create a 'fake' item for Courier to process
var fakeItem = new ContentPropertyData
{
ItemId = item.ItemId,
Name = string.Format("{0} [{1}: Nested {2} ({3})]", new[] { item.Name, EditorAlias, property.PropertyEditorAlias, property.Alias }),
Data = new List<ContentProperty>
{
new ContentProperty
{
Alias = property.Alias,
DataType = ExecutionContext.DatabasePersistence.GetUniqueId(property.DataTypeId, UmbracoNodeObjectTypeIds.DataType),
PropertyEditorAlias = property.PropertyEditorAlias,
Value = property.Value
}
}
};
if (direction == Direction.Packaging)
{
try
{
// run the 'fake' item through Courier's data resolvers
ResolutionManager.Instance.PackagingItem(fakeItem, propertyItemProvider);
}
catch (Exception ex)
{
CourierLogHelper.Error<ArchetypeDataResolver>(string.Concat("Error packaging data value: ", fakeItem.Name), ex);
}
// pass up the dependencies and resources
item.Dependencies.AddRange(fakeItem.Dependencies);
item.Resources.AddRange(fakeItem.Resources);
}
else if (direction == Direction.Extracting)
{
try
{
// run the 'fake' item through Courier's data resolvers
ResolutionManager.Instance.ExtractingItem(fakeItem, propertyItemProvider);
}
catch (Exception ex)
{
CourierLogHelper.Error<ArchetypeDataResolver>(string.Concat("Error extracting data value: ", fakeItem.Name), ex);
}
}
if (fakeItem.Data != null && fakeItem.Data.Any())
{
var firstDataType = fakeItem.Data.FirstOrDefault();
if (firstDataType != null)
{
// set the resolved property data value
property.Value = firstDataType.Value;
// (if packaging) add a dependency for the property's data-type
if (direction == Direction.Packaging)
item.Dependencies.Add(firstDataType.DataType.ToString(), ItemProviderIds.dataTypeItemProviderGuid);
}
}
}
// serialize the Archetype back to a string
propertyData.Value = archetype.SerializeForPersistence();
}
}
}
private void RetrieveAdditionalProperties(ref ArchetypePreValue preValue)
{
if (preValue == null)
return;
foreach (var fieldset in preValue.Fieldsets)
{
foreach (var property in fieldset.Properties)
{
var dataType = ExecutionContext.DatabasePersistence.RetrieveItem<DataType>(
new ItemIdentifier(property.DataTypeGuid.ToString(),
ItemProviderIds.dataTypeItemProviderGuid));
if (dataType == null)
continue;
property.PropertyEditorAlias = dataType.PropertyEditorAlias;
}
}
}
private void RetrieveAdditionalProperties(ref ArchetypeModel archetype, ArchetypePreValue preValue)
{
foreach (var fieldset in preValue.Fieldsets)
{
var fieldsetAlias = fieldset.Alias;
foreach (var fieldsetInst in archetype.Fieldsets.Where(x => x.Alias == fieldsetAlias))
{
foreach (var property in fieldset.Properties)
{
var propertyAlias = property.Alias;
foreach (var propertyInst in fieldsetInst.Properties.Where(x => x.Alias == propertyAlias))
{
propertyInst.DataTypeGuid = property.DataTypeGuid.ToString();
propertyInst.DataTypeId = ExecutionContext.DatabasePersistence.GetNodeId(
property.DataTypeGuid, UmbracoNodeObjectTypeIds.DataType);
propertyInst.PropertyEditorAlias = property.PropertyEditorAlias;
}
}
}
}
}
}
}
@@ -0,0 +1,14 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Archetype.Courier")]
[assembly: AssemblyDescription("A set of tools to support Archetype with Umbraco Courier")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Umbrella Inc Ltd")]
[assembly: AssemblyProduct("Archetype.Courier")]
[assembly: AssemblyCopyright("Copyright \xa9 Lee Kelleher, Umbrella Inc Ltd 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("6F05C431-ABBF-4D77-9D3D-5AF6C8E318AF")]
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.0.0" targetFramework="net45" />
<package id="ClientDependency" version="1.7.1.2" targetFramework="net45" />
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net45" />
<package id="ImageProcessor" version="1.8.7.0" targetFramework="net45" />
<package id="ImageProcessor.Web" version="3.2.1.0" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="4.0.20710.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="2.0.20710.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.30506.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="4.0.20710.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="4.0.20710.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
<package id="MySql.Data" version="6.6.5" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.2" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="UmbracoCms.Core" version="7.1.2" targetFramework="net45" />
<package id="xmlrpcnet" version="2.5.0" targetFramework="net45" />
</packages>
@@ -33,139 +33,167 @@
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="AutoMapper.Net4">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="businesslogic, Version=1.0.5242.22740, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\businesslogic.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ClientDependency.Core">
<HintPath>..\packages\ClientDependency.1.7.1.2\lib\ClientDependency.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ClientDependency.Core.Mvc">
<HintPath>..\packages\ClientDependency-Mvc.1.7.0.4\lib\ClientDependency.Core.Mvc.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="cms, Version=1.0.5242.22741, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\cms.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="controls, Version=1.0.5242.22742, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\controls.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="CookComputing.XmlRpcV2">
<HintPath>..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Examine, Version=0.1.55.2941, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Examine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="HtmlAgilityPack">
<HintPath>..\packages\HtmlAgilityPack.1.4.6\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImageProcessor, Version=1.9.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ImageProcessor.1.9.0.0\lib\ImageProcessor.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImageProcessor.Web, Version=3.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ImageProcessor.Web.3.2.3.0\lib\net45\ImageProcessor.Web.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="interfaces, Version=1.0.5242.22737, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\log4net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lucene.Net">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.ApplicationBlocks.Data, Version=1.0.1559.20655, Culture=neutral">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Microsoft.ApplicationBlocks.Data.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Microsoft.Web.Helpers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Mvc.FixedDisplayModes">
<HintPath>..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.1\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MiniProfiler">
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.2.1312.1622\lib\net40\Moq.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MySql.Data">
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SQLCE4Umbraco, Version=1.0.5242.22741, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\SQLCE4Umbraco.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\System.Data.SqlServerCe.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath>
<Private>True</Private>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
@@ -176,81 +204,74 @@
<Reference Include="TidyNet, Version=1.0.0.0, Culture=neutral">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\TidyNet.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco, Version=1.0.5242.22743, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Core, Version=1.0.5242.22738, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.DataLayer, Version=1.0.5242.22740, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.DataLayer.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.editorControls, Version=1.0.5242.22746, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.editorControls.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.MacroEngines, Version=1.0.5242.22747, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.MacroEngines.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.providers, Version=1.0.5242.22742, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.providers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Web.UI, Version=1.0.5242.22748, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Web.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.XmlSerializers, Version=1.0.5242.22743, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UmbracoExamine, Version=0.6.0.22741, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\UmbracoExamine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UrlRewritingNet.UrlRewriter, Version=2.0.60829.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\UrlRewritingNet.UrlRewriter.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Models\FieldsetTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PropertyValueConverter\PropertyValueConverterTests.cs" />
<Compile Include="Serialization\Base\ArchetypeJsonConverterTestBase.cs" />
<Compile Include="Serialization\Base\RegressionTestBase.cs" />
<Compile Include="Serialization\Delinter\ArchetypeJsonDelinterTest.cs" />
<Compile Include="Serialization\Regression\ArchetypeJsonConverterLegacySetUpTest.cs" />
<Compile Include="Serialization\Regression\ArchetypeJsonConverterTest.cs" />
<Compile Include="Serialization\Regression\JsonTestLegacyModelSetUp.cs" />
<Compile Include="Serialization\Regression\SerializationTestHelper.cs" />
<Compile Include="Serialization\Regression\JsonTestModels.cs" />
<Compile Include="Serialization\Regression\JsonTestStrings.cs" />
<Compile Include="Serialization\UseCases\ArchetypeJsonConverterTest.cs" />
<Compile Include="Serialization\UseCases\Complex\ArchetypeJsonConverterTest.cs" />
<Compile Include="Serialization\UseCases\Complex\JsonTestModels.cs" />
<Compile Include="Serialization\UseCases\Complex\JsonTestStrings.cs" />
<Compile Include="Serialization\UseCases\Enumerable\ArchetypeJsonConverterTest.cs" />
<Compile Include="Serialization\UseCases\Enumerable\JsonTestModels.cs" />
<Compile Include="Serialization\UseCases\Enumerable\JsonTestStrings.cs" />
<Compile Include="Serialization\UseCases\JsonTestModels.cs" />
<Compile Include="Serialization\UseCases\JsonTestStrings.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="Data\sample-1.json" />
<None Include="packages.config" />
<None Include="SupportingFiles\config\umbracoSettings.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Archetype\Archetype.Umbraco.csproj">
<Project>{7D185D41-4228-4978-ACB8-83F9A48AD94F}</Project>
<Name>Archetype.Umbraco</Name>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup />
@@ -261,7 +282,8 @@
</PreBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>xcopy $(ProjectDir)SupportingFiles\config\* $(TargetDir)config /I /O /X /E /K /D /Y</PostBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -5,9 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Archetype.PropertyConverters;
using Archetype.Tests.Serialization.UseCases;
using NUnit.Framework;
using Archetype.Tests.Serialization;
namespace Archetype.Tests.Models
{
@@ -59,25 +57,7 @@ namespace Archetype.Tests.Models
Assert.That(fieldset.GetValue<int>("link") == 3175);
Assert.That(fieldset.GetValue<bool>("show") == true);
Assert.That(fieldset.GetValue<string>("blurb") == "A blurb here");
}
[Test]
public void Can_Convert_Property_Default_Value_Types()
{
var converter = new ArchetypeValueConverter();
var result = (Archetype.Models.ArchetypeModel)converter.ConvertDataToSource(null, _sampleJson, false);
var fieldset = result.Fieldsets.First();
Assert.That(fieldset.GetValue<int>("noSuchInteger", 1234) == 1234);
Assert.That(fieldset.GetValue<bool>("noSuchBoolean", true) == true);
Assert.That(fieldset.GetValue<bool>("noSuchBoolean", false) == false);
Assert.That(fieldset.GetValue<string>("noSuchString", "noSuchString default value") == "noSuchString default value");
var contactDetails = fieldset.GetValue<ContactDetails>("noSuchContact", new ContactDetails { Address = "some street, some city", Name = "someone" });
Assert.That(contactDetails.Address == "some street, some city");
Assert.That(contactDetails.Name == "someone");
}
}
[Test]
public void Returns_String_When_No_Type_Specified()
@@ -91,6 +71,5 @@ namespace Archetype.Tests.Models
Assert.That(property is string);
Assert.That(property == "3175");
}
}
}
@@ -1,33 +0,0 @@
using Archetype.PropertyConverters;
using at = Archetype.Models;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.Base
{
public abstract class ArchetypeJsonConverterTestBase
{
public at.ArchetypeModel ConvertModelToArchetype<T>(T model)
{
var converter = new ArchetypeValueConverter();
var json = JsonConvert.SerializeObject(model);
var archetype = (at.ArchetypeModel)converter.ConvertDataToSource(null, json, false);
return archetype;
}
public string ConvertModelToArchetypeJson<T>(T model, Formatting formatting = Formatting.None)
{
return JsonConvert.SerializeObject(model, formatting);
}
public T ConvertArchetypeJsonToModel<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json);
}
public T ConvertModelToArchetypeAndBack<T>(T model)
{
var json = ConvertModelToArchetypeJson(model);
return ConvertArchetypeJsonToModel<T>(json);
}
}
}
@@ -1,166 +0,0 @@
using System.Collections;
using System.Linq;
using System.Reflection;
using Archetype.Serialization;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Persistence;
using Umbraco.Core.Services;
namespace Archetype.Tests.Serialization.Base
{
public abstract class RegressionTestBase : ArchetypeJsonConverterTestBase
{
protected void SimpleModel_Regression_Battery<T>(T model)
{
var archetype = ConvertModelToArchetype(model);
Assert.IsNotNull(archetype);
var archetypeJson = archetype.SerializeForPersistence();
var modelJson = ConvertModelToArchetypeJson(model, Formatting.Indented);
Assert.IsNotNullOrEmpty(modelJson);
var result = ConvertModelToArchetypeAndBack(model);
var resultfromArchetypeJson = ConvertArchetypeJsonToModel<T>(archetypeJson);
Assert.IsInstanceOf<T>(result);
Assert.IsInstanceOf<T>(resultfromArchetypeJson);
AssertAreEqual(model, result);
AssertAreEqual(model, resultfromArchetypeJson);
}
protected void SimpleModels_Regression_Battery<T>(T model)
where T : IList
{
var archetype = ConvertModelToArchetype(model);
Assert.IsNotNull(archetype);
var archetypeJson = archetype.SerializeForPersistence();
var modelJson = ConvertModelToArchetypeJson(model, Formatting.Indented);
Assert.IsNotNullOrEmpty(modelJson);
var result = ConvertModelToArchetypeAndBack(model);
var resultfromArchetypeJson = ConvertArchetypeJsonToModel<T>(archetypeJson);
Assert.IsInstanceOf<T>(result);
Assert.IsInstanceOf<T>(resultfromArchetypeJson);
Assert.AreEqual(model.Count, result.Count);
Assert.AreEqual(model.Count, resultfromArchetypeJson.Count);
foreach (var resultItem in result)
{
var index = result.IndexOf(resultItem);
AssertAreEqual(model[index], resultItem);
}
foreach (var resultItem in resultfromArchetypeJson)
{
var index = resultfromArchetypeJson.IndexOf(resultItem);
AssertAreEqual(model[index], resultItem);
}
}
protected void CompoundModel_Regression_Battery<T>(T model)
{
var archetype = ConvertModelToArchetype(model);
Assert.IsNotNull(archetype);
var archetypeJson = archetype.SerializeForPersistence();
var modelJson = ConvertModelToArchetypeJson(model, Formatting.Indented);
Assert.IsNotNullOrEmpty(modelJson);
var result = ConvertModelToArchetypeAndBack(model);
var resultfromArchetypeJson = ConvertArchetypeJsonToModel<T>(archetypeJson);
Assert.IsInstanceOf<T>(result);
AssertAreEqual(model, result);
Assert.IsInstanceOf<T>(resultfromArchetypeJson);
AssertAreEqual(model, resultfromArchetypeJson);
}
protected void NestedModel_Regression_Battery<T>(T model)
{
CompoundModel_Regression_Battery(model);
}
protected void ComplexModel_Regression_Battery<T>(T model)
{
CompoundModel_Regression_Battery(model);
}
protected void AssertAreEqual<T>(T model, T result)
{
foreach (var propInfo in model.GetSerialiazableProperties())
{
var expected = GetExpectedValue(model, propInfo);
var actual = GetActualValue(result, propInfo);
if (propInfo.PropertyType.Namespace.Equals("System"))
{
Assert.AreEqual(expected, actual);
continue;
}
var list = expected as IList;
if (list != null)
{
foreach (var expectedItem in list)
{
var index = list.IndexOf(expectedItem);
AssertAreEqual(expectedItem, ((IList)actual)[index]);
}
continue;
}
AssertAreEqual(expected, actual);
}
}
protected void EnsureUmbracoContext(Mock<IDataTypeService> dataTypeService)
{
var cacheHelper = CacheHelper.CreateDisabledCacheHelper();
var serviceContext = new ServiceContext(
Mock.Of<IContentService>(),
Mock.Of<IMediaService>(),
Mock.Of<IContentTypeService>(),
dataTypeService.Object,
Mock.Of<IFileService>(),
Mock.Of<ILocalizationService>(),
Mock.Of<IPackagingService>(),
Mock.Of<IEntityService>(),
Mock.Of<IRelationService>(),
Mock.Of<IMemberGroupService>(),
Mock.Of<IMemberTypeService>(),
Mock.Of<IMemberService>(),
Mock.Of<IUserService>(),
Mock.Of<ISectionService>(),
Mock.Of<IApplicationTreeService>(),
Mock.Of<ITagService>(),
Mock.Of<INotificationService>()
);
ApplicationContext.EnsureContext(
new DatabaseContext(Mock.Of<IDatabaseFactory>()), serviceContext, cacheHelper, true);
}
private object GetExpectedValue<T>(T expected, PropertyInfo propInfo)
{
return propInfo.GetValue(expected, null);
}
private object GetActualValue<T>(T actual, PropertyInfo propInfo)
{
var actualProp = actual.GetSerialiazableProperties().SingleOrDefault(pinfo => pinfo.Name.Equals(propInfo.Name));
return actualProp != null
? actualProp.GetValue(actual, null)
: null;
}
}
}
@@ -1,253 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.PropertyEditors;
using Archetype.Serialization;
using Archetype.Tests.Serialization.Base;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
namespace Archetype.Tests.Serialization.Delinter
{
[TestFixture]
public class ArchetypeJsonDelinterTest : RegressionTestBase
{
private const string _ESCAPED_JSON = @"{""fieldsets"":[{""properties"":[{""alias"":""slides"",""value"":""2680""}],""alias"":""slides""},{""properties"":[{""alias"":""captions"",""value"":""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test1 test1\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test2 test2\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test3b test3b\""}],\""alias\"":\""textstringArray\""}]}""}],""alias"":""captions""}]}";
private const string _JSON = @"{""fieldsets"":[{""properties"":[{""alias"":""slides"",""value"":""2680""}],""alias"":""slides""},{""properties"":[{""alias"":""captions"",""value"":{""fieldsets"":[{""properties"":[{""alias"":""textstring"",""value"":""test1 test1""}],""alias"":""textstringArray""},{""properties"":[{""alias"":""textstring"",""value"":""test2 test2""}],""alias"":""textstringArray""},{""properties"":[{""alias"":""textstring"",""value"":""test3b test3b""}],""alias"":""textstringArray""}]}}],""alias"":""captions""}]}";
private const string _ESCAPED_JSON_DEEP_NESTED = @"{""fieldsets"":[{""properties"":[{""alias"":""pages"",""value"":""""},{""alias"":""captions"",""value"":""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""captions\"",\""value\"":\""{\\\""fieldsets\\\"":[{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\""}],\\\""alias\\\"":\\\""textList\\\""}]}\""}],\""alias\"":\""captions\""}]}""}],""alias"":""pages""}]}";
private const string _ESCAPED_JSON_FROM_APP = @"{
""alias"": ""captions"",
""value"": ""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test1 test1\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test2 test2\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test3b test3b\""}],\""alias\"":\""textstringArray\""}]}""
}";
private SlideShow _referenceModel;
private NestedClass _nestedClass;
[SetUp]
public void SetUp()
{
_referenceModel = new SlideShow()
{
Slides = "2680",
Captions = new Captions()
{
new TextString(){Text = "test1 test1"},
new TextString(){Text = "test2 test2"},
new TextString(){Text = "test3b test3b"}
}
};
_nestedClass = GetNestedClass();
_nestedClass.SlideShow = _referenceModel;
_nestedClass.Nested = GetNestedClass();
_nestedClass.Nested.SlideShow = _referenceModel;
_nestedClass.Nested.Nested = GetNestedClass();
}
[Test]
public void Delinter_RemoveNewLine_ByPasses_Values()
{
const string _JSON_WITH_RESERVED_CHARS = @"{
""alias"": ""captions"",
""value"": ""{ \""fieldsets\"": [
{
\""properties\"":
[
{ \""alias\"": \""textstring\"" , \""value\"":\""test1 \r\n test1\r\n\""}], \""alias\"":\""textstringArray\"" },{\""properties\"": [ { \""alias\"":\""textstring\"",\""value\"":\""test2\r\ntest2\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test3b \""quote\"" \\r\\r\\rtest3\""}],\""alias\"":\""textstringArray\"" } ] }""
}";
var referenceModel = new Captions()
{
new TextString() {Text = @"test1
test1
"},
new TextString() {Text = @"test2
test2"},
new TextString() {Text = @"test3b ""quote"" \r\r\rtest3"}
};
var delintedJson = _JSON_WITH_RESERVED_CHARS.DelintArchetypeJson();
var actualModel = ConvertArchetypeJsonToModel<Captions>(delintedJson);
var t = JToken.Parse(delintedJson).ToString(Formatting.None);
Assert.IsInstanceOf<Captions>(actualModel);
Assert.IsNotNull(actualModel);
Assert.AreEqual(3, actualModel.Count);
foreach (var refItem in referenceModel)
{
var index = referenceModel.IndexOf(refItem);
AssertAreEqual(refItem, actualModel.ElementAt(index));
}
}
[Test]
public void ReferenceJsonAndModel_Equal_ExpectedJsonAndModel()
{
const string expectedJson = _JSON;
var expectedModel = ConvertArchetypeJsonToModel<SlideShow>(expectedJson);
var referenceModel = ConvertModelToArchetypeAndBack(_referenceModel);
Assert.IsInstanceOf<SlideShow>(expectedModel);
Assert.IsInstanceOf<SlideShow>(referenceModel);
Assert.AreEqual(3, expectedModel.Captions.Count);
Assert.AreEqual(3, referenceModel.Captions.Count);
AssertAreEqual(expectedModel, referenceModel);
}
[Test]
public void UnescapedJsonAndModel_Equal_ExpectedJsonAndModel()
{
const string expectedJson = _JSON;
var unescapedJson = _ESCAPED_JSON.DelintArchetypeJson();
var expectedModel = ConvertArchetypeJsonToModel<SlideShow>(expectedJson);
var actualModel = ConvertArchetypeJsonToModel<SlideShow>(unescapedJson);
Assert.IsInstanceOf<SlideShow>(expectedModel);
Assert.IsInstanceOf<SlideShow>(actualModel);
Assert.AreEqual(3, expectedModel.Captions.Count);
Assert.AreEqual(3, actualModel.Captions.Count);
AssertAreEqual(expectedModel, actualModel);
}
[Test]
public void EscapedJson_FromApp_SerializesToModel()
{
var delintedJson = _ESCAPED_JSON_FROM_APP.DelintArchetypeJson();
var referenceModel = new Captions()
{
new TextString() {Text = "test1 test1"},
new TextString() {Text = "test2 test2"},
new TextString() {Text = "test3b test3b"}
};
var actualModel = ConvertArchetypeJsonToModel<Captions>(delintedJson);
Assert.IsInstanceOf<Captions>(actualModel);
Assert.AreEqual(3, actualModel.Count);
foreach (var refItem in referenceModel)
{
var index = referenceModel.IndexOf(refItem);
AssertAreEqual(refItem, actualModel.ElementAt(index));
}
}
[Test]
public void DeepNestedJson_Escapes_Correctly()
{
var propGuid = new Guid();
var dtd = new DataTypeDefinition(-1, String.Empty) { Id = 0 };
var dataTypeService = new Mock<IDataTypeService>();
dataTypeService.Setup(dts => dts.GetDataTypeDefinitionById(Guid.Parse(propGuid.ToString()))).Returns(dtd);
dataTypeService.Setup(dts => dts.GetPreValuesCollectionByDataTypeId(dtd.Id)).Returns(new PreValueCollection(new Dictionary<string, PreValue>()));
var propValueEditor = new Mock<ArchetypePropertyEditor.ArchetypePropertyValueEditor>(new PropertyValueEditor());
propValueEditor.Setup(pe => pe.GetPropertyEditor(dtd)).Returns(new ArchetypePropertyEditor());
var archetype = ConvertModelToArchetype(_nestedClass);
foreach (var prop in archetype.Fieldsets.SelectMany(fs => fs.Properties))
{
prop.DataTypeGuid = propGuid.ToString();
if (prop.Value.ToString().Contains("fieldsets"))
prop.PropertyEditorAlias = Constants.PropertyEditorAlias;
}
var archetypeJson = JsonConvert.SerializeObject(archetype);
Assert.IsNotNullOrEmpty(archetypeJson);
EnsureUmbracoContext(dataTypeService);
var propEditor = new ArchetypePropertyEditor.ArchetypePropertyValueEditor(new PropertyValueEditor());
var convertedJson = propEditor.ConvertEditorToDb(new ContentPropertyData(JObject.FromObject(archetype),
new PreValueCollection(new Dictionary<string, PreValue>()), new Dictionary<string, object>()),
archetypeJson);
Assert.IsNotNull(convertedJson);
var delintedJson = convertedJson.ToString().DelintArchetypeJson();
Assert.IsNotNullOrEmpty(delintedJson);
var modelfromArchetypeJson = ConvertArchetypeJsonToModel<NestedClass>(archetypeJson);
var modelfromConvertedJson = ConvertArchetypeJsonToModel<NestedClass>(delintedJson);
Assert.IsInstanceOf<NestedClass>(modelfromArchetypeJson);
Assert.IsInstanceOf<NestedClass>(modelfromConvertedJson);
Assert.AreEqual(3, modelfromArchetypeJson.SlideShow.Captions.Count);
Assert.AreEqual(3, modelfromConvertedJson.SlideShow.Captions.Count);
Assert.AreEqual(3, modelfromArchetypeJson.Nested.SlideShow.Captions.Count);
Assert.AreEqual(3, modelfromConvertedJson.Nested.SlideShow.Captions.Count);
AssertAreEqual(modelfromArchetypeJson, modelfromConvertedJson);
}
#region private methods
private NestedClass GetNestedClass()
{
return new NestedClass();
}
#endregion
#region classes
[AsArchetype("slides")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SlideShow
{
[JsonProperty("slides")]
public string Slides { get; set; }
[AsFieldset]
[JsonProperty("captions")]
public Captions Captions { get; set; }
}
[AsArchetype("textstringArray")] /* Note: when inheriting from a list, archetype alias is not used */
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Captions : List<TextString>
{
}
[AsArchetype("textstringArray")] /* due to hard coded string calues above, must have same archetype alias as list class */
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextString
{
[JsonProperty("textstring")]
public String Text { get; set; }
}
[AsArchetype("nestedClass")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class NestedClass
{
[JsonProperty("nestedClass")]
public NestedClass Nested { get; set; }
[JsonProperty("slides")]
public SlideShow SlideShow { get; set; }
}
#endregion
}
}
@@ -1,25 +0,0 @@
using System.Linq;
using Newtonsoft.Json;
using NUnit.Framework;
namespace Archetype.Tests.Serialization.Regression
{
[TestFixture]
public class ArchetypeJsonConverterLegacySetUpTest
{
[Test]
public void Deserialize_SlideShow_FromArchetype()
{
var result = JsonConvert.DeserializeObject<SlideShow>(JsonTestStrings._SLIDES_JSON);
Assert.NotNull(result);
Assert.IsInstanceOf<SlideShow>(result);
Assert.AreEqual("1,2,3,4,5", result.Slides);
Assert.AreEqual("Test 1", result.Captions.TextStringArray.ElementAt(0).Text);
Assert.AreEqual("Test 2", result.Captions.TextStringArray.ElementAt(1).Text);
Assert.AreEqual("Test 3", result.Captions.TextStringArray.ElementAt(2).Text);
Assert.AreEqual("Test 4", result.Captions.TextStringArray.ElementAt(3).Text);
}
}
}
@@ -1,150 +0,0 @@
using Archetype.Tests.Serialization.Base;
using Newtonsoft.Json;
using NUnit.Framework;
namespace Archetype.Tests.Serialization.Regression
{
[TestFixture]
public class ArchetypeJsonConverterTest : RegressionTestBase
{
private SerializationTestHelper _testHelper;
[SetUp]
public void SetUp()
{
_testHelper = new SerializationTestHelper();
}
[Test]
public void EmptyArray_Returns_Null()
{
var archetypeJson = @"{""fieldsets"": []}";
var result = ConvertArchetypeJsonToModel<SimpleModel>(archetypeJson);
Assert.IsNull(result);
}
[Test]
public void SimpleModel_Regression_Battery()
{
var simpleModel = _testHelper.GetModel<SimpleModel>();
SimpleModel_Regression_Battery(simpleModel);
var json = ConvertModelToArchetypeJson(simpleModel, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._SIMPLE_JSON, json);
}
[Test]
public void SimpleModelWithFieldsets_Regression_Battery()
{
var simpleModel = _testHelper.GetModel<SimpleModelWithFieldsets>();
SimpleModel_Regression_Battery(simpleModel);
}
[Test]
public void SimpleModelWithMixedFieldsets_Regression_Battery()
{
var simpleModel = _testHelper.GetModel<SimpleModelWithMixedFieldsets>();
SimpleModel_Regression_Battery(simpleModel);
}
[Test]
public void SimpleModels_Regression_Battery()
{
var simpleModels = _testHelper.GetModel<SimpleModels>();
SimpleModels_Regression_Battery(simpleModels);
}
[Test]
public void SimpleModelsWithFieldsets_Regression_Battery()
{
var simpleModels = _testHelper.GetModel<SimpleModelsWithFieldsets>();
SimpleModels_Regression_Battery(simpleModels);
}
[Test]
public void SimpleModelsWithMixedFieldsets_Regression_Battery()
{
var simpleModels = _testHelper.GetModel<SimpleModelsWithMixedFieldsets>();
SimpleModels_Regression_Battery(simpleModels);
}
[Test]
public void CompoundModel_Regression_Battery()
{
var compoundModel = _testHelper.GetModel<CompoundModel>();
CompoundModel_Regression_Battery(compoundModel);
}
[Test]
public void CompoundModelWithMixedFieldsetVariant1_Regression_Battery()
{
var compoundModel = _testHelper.GetModel<CompoundModelWithMixedFieldsetVariant1>();
CompoundModel_Regression_Battery(compoundModel);
}
[Test]
public void CompoundModelWithMixedFieldsetVariant2_Regression_Battery()
{
var compoundModel = _testHelper.GetModel<CompoundModelWithMixedFieldsetVariant2>();
CompoundModel_Regression_Battery(compoundModel);
}
[Test]
public void CompoundModelWithFieldset_Regression_Battery()
{
var compoundModel = _testHelper.GetModel<CompoundModelWithFieldset>();
CompoundModel_Regression_Battery(compoundModel);
}
[Test]
public void CompoundModelWithList_Regression_Battery()
{
var compoundModelWithList = _testHelper.GetModel<CompoundModelWithList>();
CompoundModel_Regression_Battery(compoundModelWithList);
}
[Test]
public void CompoundModelWithMixedFieldsetWithList_Regression_Battery()
{
var compoundModelWithList = _testHelper.GetModel<CompoundModelWithMixedFieldsetWithList>();
CompoundModel_Regression_Battery(compoundModelWithList);
}
[Test]
public void CompoundModelWithFieldsetWithList_Regression_Battery()
{
var compoundModelWithList = _testHelper.GetModel<CompoundModelWithFieldsetWithList>();
CompoundModel_Regression_Battery(compoundModelWithList);
}
[Test]
public void NestedModel_Regression_Battery()
{
var nestedModel = _testHelper.GetModel<NestedModel>();
NestedModel_Regression_Battery(nestedModel);
}
[Test]
public void NestedModelWithMixedFieldset_Regression_Battery()
{
var nestedModel = _testHelper.GetModel<NestedModelWithMixedFieldset>();
NestedModel_Regression_Battery(nestedModel);
}
[Test]
public void NestedModelWithFieldset_Regression_Battery()
{
var nestedModel = _testHelper.GetModel<NestedModelWithFieldset>();
NestedModel_Regression_Battery(nestedModel);
}
[Test]
public void ComplexModel_Regression_Battery()
{
var complexModel = _testHelper.GetModel<ComplexModel>();
NestedModel_Regression_Battery(complexModel);
}
}
}
@@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using Archetype.Serialization;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.Regression
{
[AsArchetype("textstringArray")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextString
{
[JsonProperty("textstring")]
public String Text { get; set; }
}
[AsArchetype("textstringArray")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextStringArray : List<TextString>
{
}
[AsArchetype("captions")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Captions
{
[JsonProperty("captions")]
public TextStringArray TextStringArray { get; set; }
}
[AsArchetype("slides")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SlideShow
{
[JsonProperty("slides")]
public string Slides { get; set; }
[AsFieldset]
[JsonProperty("captions")]
public Captions Captions { get; set; }
}
}
@@ -1,257 +0,0 @@
using System;
using System.Collections.Generic;
using Archetype.Serialization;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.Regression
{
[AsArchetype("simpleModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModel
{
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
[JsonProperty("nullableInteger")]
public int? NullableId { get; set; }
[JsonProperty("double")]
public double Amount { get; set; }
[JsonProperty("nullableDouble")]
public double? NullableAmount { get; set; }
[JsonProperty("dateTime")]
public DateTime DateOne { get; set; }
[JsonProperty("nullableDateTime")]
public DateTime? DateTwo { get; set; }
}
[AsArchetype("simpleModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModelWithFieldsets
{
[AsFieldset]
[JsonProperty("text")]
public string Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
[AsFieldset]
[JsonProperty("nullableInteger")]
public int? NullableId { get; set; }
[AsFieldset]
[JsonProperty("double")]
public double Amount { get; set; }
[AsFieldset]
[JsonProperty("nullableDouble")]
public double? NullableAmount { get; set; }
[AsFieldset]
[JsonProperty("dateTime")]
public DateTime DateOne { get; set; }
[AsFieldset]
[JsonProperty("nullableDateTime")]
public DateTime? DateTwo { get; set; }
}
[AsArchetype("simpleModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModelWithMixedFieldsets
{
[AsFieldset]
[JsonProperty("text")]
public string Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
[AsFieldset]
[JsonProperty("nullableInteger")]
public int? NullableId { get; set; }
[JsonProperty("double")]
public double Amount { get; set; }
[AsFieldset]
[JsonProperty("nullableDouble")]
public double? NullableAmount { get; set; }
[AsFieldset]
[JsonProperty("dateTime")]
public DateTime DateOne { get; set; }
public DateTime? DateTwo { get; set; }
}
[AsArchetype("simpleModels")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModels : List<SimpleModel>
{
}
[AsArchetype("simpleModels")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModelsWithFieldsets : List<SimpleModelWithFieldsets>
{
}
[AsArchetype("simpleModels")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SimpleModelsWithMixedFieldsets : List<SimpleModelWithMixedFieldsets>
{
}
[AsArchetype("compoundModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModel
{
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModelWithMixedFieldset")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithMixedFieldsetVariant1
{
[AsFieldset]
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModelWithMixedFieldset")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithMixedFieldsetVariant2
{
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[AsFieldset]
[JsonProperty("text")]
public String Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithFieldset
{
[AsFieldset]
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[AsFieldset]
[JsonProperty("text")]
public String Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModelWithList")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithList
{
[JsonProperty("simpleModelList")]
public List<SimpleModel> SimpleModelList { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModelWithList")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithMixedFieldsetWithList
{
[JsonProperty("simpleModelList")]
public List<SimpleModel> SimpleModelList { get; set; }
[AsFieldset]
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("compoundModelWithList")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWithFieldsetWithList
{
[AsFieldset]
[JsonProperty("simpleModelList")]
public List<SimpleModel> SimpleModelList { get; set; }
[AsFieldset]
[JsonProperty("text")]
public String Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("nestedModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class NestedModel
{
[JsonProperty("compoundModel")]
public CompoundModel CompoundModel { get; set; }
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("nestedModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class NestedModelWithMixedFieldset
{
[JsonProperty("compoundModel")]
public CompoundModel CompoundModel { get; set; }
[AsFieldset]
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("nestedModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class NestedModelWithFieldset
{
[AsFieldset]
[JsonProperty("compoundModel")]
public CompoundModel CompoundModel { get; set; }
[AsFieldset]
[JsonProperty("simpleModel")]
public SimpleModel SimpleModel { get; set; }
[AsFieldset]
[JsonProperty("text")]
public String Text { get; set; }
[AsFieldset]
[JsonProperty("integer")]
public int Id { get; set; }
}
[AsArchetype("complexModel")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class ComplexModel
{
[JsonProperty("compoundModels")]
public CompoundModelWrapper CompoundModelWrapper { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
}
[AsArchetype("compoundModelWrapper")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompoundModelWrapper
{
[JsonProperty("compoundModels")]
public List<CompoundModel> CompoundModels { get; set; }
[JsonProperty("text")]
public String Text { get; set; }
}
}
@@ -1,124 +0,0 @@
namespace Archetype.Tests.Serialization.Regression
{
public class JsonTestStrings
{
public const string _SIMPLE_JSON = @"{
""fieldsets"": [
{
""alias"": ""simpleModel"",
""properties"": [
{
""alias"": ""text"",
""value"": ""Test \r\nText \""quote\"" \r\n""
},
{
""alias"": ""integer"",
""value"": ""123""
},
{
""alias"": ""nullableInteger"",
""value"": """"
},
{
""alias"": ""double"",
""value"": ""5.67""
},
{
""alias"": ""nullableDouble"",
""value"": """"
},
{
""alias"": ""dateTime"",
""value"": ""01/01/2000 00:00:00""
},
{
""alias"": ""nullableDateTime"",
""value"": """"
}
]
}
]
}";
public const string _ESCAPED_JSON =
@"{
""fieldsets"":[
{
""properties"":[
{
""alias"":""pages"",
""value"":""2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453""
},
{
""alias"":""captions"",
""value"":""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""captions\"",\""value\"":\""{\\\""fieldsets\\\"":[{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""First Page\\\\\\\"",\\\\\\\""propertyEditorAlias\\\\\\\"":\\\\\\\""Umbraco.Textbox\\\\\\\"",\\\\\\\""dataTypeId\\\\\\\"":-88,\\\\\\\""dataTypeGuid\\\\\\\"":\\\\\\\""0cc0eba1-9960-42c9-bf9b-60e150b429ae\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\"",\\\""propertyEditorAlias\\\"":\\\""Imulus.Archetype\\\"",\\\""dataTypeId\\\"":3764,\\\""dataTypeGuid\\\"":\\\""496cfe35-448f-4b59-9c75-050798afdce4\\\""}],\\\""alias\\\"":\\\""textList\\\""},{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""Second Page\\\\\\\"",\\\\\\\""propertyEditorAlias\\\\\\\"":\\\\\\\""Umbraco.Textbox\\\\\\\"",\\\\\\\""dataTypeId\\\\\\\"":-88,\\\\\\\""dataTypeGuid\\\\\\\"":\\\\\\\""0cc0eba1-9960-42c9-bf9b-60e150b429ae\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\"",\\\""propertyEditorAlias\\\"":\\\""Imulus.Archetype\\\"",\\\""dataTypeId\\\"":3764,\\\""dataTypeGuid\\\"":\\\""496cfe35-448f-4b59-9c75-050798afdce4\\\""}],\\\""alias\\\"":\\\""textList\\\""},{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""Third Page\\\\\\\"",\\\\\\\""propertyEditorAlias\\\\\\\"":\\\\\\\""Umbraco.Textbox\\\\\\\"",\\\\\\\""dataTypeId\\\\\\\"":-88,\\\\\\\""dataTypeGuid\\\\\\\"":\\\\\\\""0cc0eba1-9960-42c9-bf9b-60e150b429ae\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\"",\\\""propertyEditorAlias\\\"":\\\""Imulus.Archetype\\\"",\\\""dataTypeId\\\"":3764,\\\""dataTypeGuid\\\"":\\\""496cfe35-448f-4b59-9c75-050798afdce4\\\""}],\\\""alias\\\"":\\\""textList\\\""},{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""Fourth Page\\\\\\\"",\\\\\\\""propertyEditorAlias\\\\\\\"":\\\\\\\""Umbraco.Textbox\\\\\\\"",\\\\\\\""dataTypeId\\\\\\\"":-88,\\\\\\\""dataTypeGuid\\\\\\\"":\\\\\\\""0cc0eba1-9960-42c9-bf9b-60e150b429ae\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\"",\\\""propertyEditorAlias\\\"":\\\""Imulus.Archetype\\\"",\\\""dataTypeId\\\"":3764,\\\""dataTypeGuid\\\"":\\\""496cfe35-448f-4b59-9c75-050798afdce4\\\""}],\\\""alias\\\"":\\\""textList\\\""}]}\"",\""propertyEditorAlias\"":\""Imulus.Archetype\"",\""dataTypeId\"":3765,\""dataTypeGuid\"":\""4ed439b3-0ee7-447a-a64e-b2b486b86379\""}],\""alias\"":\""captions\""}]}""
}
],
""alias"":""pages""
}
]
}";
public const string _SLIDES_JSON =
@"{
""fieldsets"": [
{
""alias"": ""captions"",
""properties"": [
{
""alias"": ""captions"",
""value"": {
""fieldsets"": [
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Test 1""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Test 2""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Test 3""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Test 4""
}
]
}
]
}
}
]
},
{
""alias"": ""slides"",
""properties"": [
{
""alias"": ""slides"",
""value"": ""1,2,3,4,5""
}
]
}
]
}";
}
}
@@ -1,220 +0,0 @@
using System;
using System.Collections.Generic;
namespace Archetype.Tests.Serialization.Regression
{
public class SerializationTestHelper
{
public T GetModel<T>()
{
try
{
return (T)GetType().GetMethod("Get" + typeof(T).Name).Invoke(this, null);
}
catch
{
return default(T);
}
}
public SimpleModel GetSimpleModel()
{
return new SimpleModel
{
Amount = 5.67,
NullableAmount = null,
DateOne = new DateTime(2000, 1, 1),
DateTwo = null,
Id = 123,
NullableId = null,
Text = @"Test
Text ""quote""
"
};
}
public SimpleModelWithFieldsets GetSimpleModelWithFieldsets()
{
return new SimpleModelWithFieldsets
{
Amount = 5.67,
NullableAmount = null,
DateOne = new DateTime(2000, 1, 1),
DateTwo = null,
Id = 123,
NullableId = null,
Text = "Test Text"
};
}
public SimpleModelWithMixedFieldsets GetSimpleModelWithMixedFieldsets()
{
return new SimpleModelWithMixedFieldsets
{
Amount = 5.67,
NullableAmount = null,
DateOne = new DateTime(2000, 1, 1),
DateTwo = null,
Id = 123,
NullableId = null,
Text = "Test Text"
};
}
public SimpleModels GetSimpleModels()
{
return new SimpleModels
{
GetSimpleModel(),
GetSimpleModel(),
GetSimpleModel()
};
}
public SimpleModelsWithFieldsets GetSimpleModelsWithFieldsets()
{
return new SimpleModelsWithFieldsets
{
GetSimpleModelWithFieldsets(),
GetSimpleModelWithFieldsets(),
GetSimpleModelWithFieldsets()
};
}
public SimpleModelsWithMixedFieldsets GetSimpleModelsWithMixedFieldsets()
{
return new SimpleModelsWithMixedFieldsets
{
GetSimpleModelWithMixedFieldsets(),
GetSimpleModelWithMixedFieldsets(),
GetSimpleModelWithMixedFieldsets()
};
}
public CompoundModel GetCompoundModel()
{
return new CompoundModel
{
Id = -1,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(CompoundModel).Name
};
}
public CompoundModelWithMixedFieldsetVariant1 GetCompoundModelWithMixedFieldsetVariant1()
{
return new CompoundModelWithMixedFieldsetVariant1
{
Id = -1,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(CompoundModelWithMixedFieldsetVariant1).Name
};
}
public CompoundModelWithMixedFieldsetVariant2 GetCompoundModelWithMixedFieldsetVariant2()
{
return new CompoundModelWithMixedFieldsetVariant2
{
Id = -1,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(CompoundModelWithMixedFieldsetVariant2).Name
};
}
public CompoundModelWithFieldset GetCompoundModelWithFieldset()
{
return new CompoundModelWithFieldset
{
Id = -1,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(CompoundModelWithFieldset).Name
};
}
public CompoundModelWithList GetCompoundModelWithList()
{
return new CompoundModelWithList
{
Id = 10,
SimpleModelList = GetModel<SimpleModels>(),
Text = typeof(CompoundModelWithList).Name
};
}
public CompoundModelWithMixedFieldsetWithList GetCompoundModelWithMixedFieldsetWithList()
{
return new CompoundModelWithMixedFieldsetWithList
{
Id = 11,
SimpleModelList = GetModel<SimpleModels>(),
Text = typeof(CompoundModelWithMixedFieldsetWithList).Name
};
}
public CompoundModelWithFieldsetWithList GetCompoundModelWithFieldsetWithList()
{
return new CompoundModelWithFieldsetWithList
{
Id = 12,
SimpleModelList = GetModel<SimpleModels>(),
Text = typeof(CompoundModelWithFieldsetWithList).Name
};
}
public NestedModel GetNestedModel()
{
return new NestedModel
{
CompoundModel = GetModel<CompoundModel>(),
Id = 53,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(NestedModel).Name
};
}
public NestedModelWithMixedFieldset GetNestedModelWithMixedFieldset()
{
return new NestedModelWithMixedFieldset
{
CompoundModel = GetModel<CompoundModel>(),
Id = 54,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(NestedModelWithMixedFieldset).Name
};
}
public NestedModelWithFieldset GetNestedModelWithFieldset()
{
return new NestedModelWithFieldset
{
CompoundModel = GetModel<CompoundModel>(),
Id = 55,
SimpleModel = GetModel<SimpleModel>(),
Text = typeof(NestedModelWithFieldset).Name
};
}
public CompoundModelWrapper GetCompoundModelWrapper()
{
return new CompoundModelWrapper
{
CompoundModels = new List<CompoundModel>
{
GetModel<CompoundModel>(),
GetModel<CompoundModel>(),
GetModel<CompoundModel>()
},
Text = typeof(CompoundModelWrapper).Name
};
}
public ComplexModel GetComplexModel()
{
return new ComplexModel
{
CompoundModelWrapper = GetModel<CompoundModelWrapper>(),
Text = typeof(ComplexModel).Name
};
}
}
}
@@ -1,343 +0,0 @@
using System;
using Archetype.Tests.Serialization.Base;
using Newtonsoft.Json;
using NUnit.Framework;
namespace Archetype.Tests.Serialization.UseCases
{
[TestFixture]
public class ArchetypeJsonConverterTest : ArchetypeJsonConverterTestBase
{
private ContactDetails _contactDetails;
private CompanyDetails _companyDetails;
private AnnualStatement _annualStatement;
private MergerDetails _mergerDetails;
private UrlPicker _webSite;
[SetUp]
public void SetUp()
{
_webSite = new UrlPicker
{
Url = "http://test.com",
Title = "The Test Company",
OpenInNewWindow = true
};
_mergerDetails = new MergerDetails
{
MergerDate = new DateTime(2014,6,7,8,9,10),
MergerValue = 12345676890.12m
};
_contactDetails = new ContactDetails
{
Address = "Test Address",
Email = "test@test.com",
Fax = "000",
Mobile = "000",
Name = "Test",
Telephone = "111",
WebSite = _webSite
};
_companyDetails = new CompanyDetails
{
Region = "Test Region",
ContactDetails = _contactDetails
};
_annualStatement = new AnnualStatement
{
FiscalYearStart = new DateTime(2013, 9, 1),
FiscalYearEnd = new DateTime(2014, 8, 31),
TotalShares = 345678,
Sales = 123456700.89,
Profit = 1123456.78m
};
}
#region serialization tests
[Test]
public void Convert_MergerDetailsModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_mergerDetails, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._MERGER_DETAILS_JSON, result);
}
[Test]
public void Convert_ContactDetailsModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_contactDetails, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._CONTACT_DETAILS_JSON, result);
}
[Test]
public void Convert_CompanyDetailsModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_companyDetails, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._COMPANY_DETAILS_JSON, result);
}
[Test]
public void Convert_AnnualStatementModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_annualStatement, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._ANNUAL_STATEMENT_JSON, result);
}
[Test]
public void NullValues_Serialize_To_Empty_String()
{
var result = ConvertModelToArchetypeJson(new ContactDetails());
Assert.AreEqual(JsonTestStrings._NULL_VALUES_JSON, result);
}
[Test]
public void Convert_ContactDetailsModel_To_Archetype()
{
var model = new ContactDetails
{
Address = "addr",
Email = "email"
};
Assert.NotNull(ConvertModelToArchetype(model));
}
[Test]
public void Convert_AnnualStatementModel_To_Archetype()
{
Assert.NotNull(ConvertModelToArchetype(_annualStatement));
}
[Test]
public void Convert_AllContactDetailsModel_To_Archetype()
{
var item1 = new ContactDetails
{
Address = "addr",
Email = "email"
};
var item2 = new ContactDetails
{
Address = "addr1",
Name = "email2"
};
var model = new AllContactDetails
{
UserDetails = item1,
AdminDetails = item2
};
Assert.NotNull(ConvertModelToArchetype(model));
}
[Test]
public void Convert_ContactDetailsListModel_To_Archetype()
{
var item1 = new ContactDetails
{
Address = "addr",
Email = "email"
};
var item2 = new ContactDetails
{
Address = "addr1",
Name = "email2"
};
var model = new ContactDetailsList
{
item1,
item2
};
Assert.NotNull(ConvertModelToArchetype(model));
}
[Test]
public void Convert_CompanyDetailsModel_To_Archetype()
{
var model = new CompanyDetails
{
Region = "Test Region",
ContactDetails = new ContactDetails
{
Address = "addr1",
Name = "email2"
}
};
Assert.NotNull(ConvertModelToArchetype(model));
}
#endregion
#region deserialization tests
[Test]
public void Convert_ArchetypeJson_To_ContactDetailsModel()
{
var result = ConvertArchetypeJsonToModel<ContactDetails>(JsonTestStrings._CONTACT_DETAILS_JSON);
Assert.NotNull(result);
Assert.IsInstanceOf<ContactDetails>(result);
Assert.AreEqual("Test Address", result.Address);
Assert.AreEqual("test@test.com", result.Email);
Assert.AreEqual("000", result.Fax);
Assert.AreEqual("000", result.Mobile);
Assert.AreEqual("Test", result.Name);
Assert.AreEqual("111", result.Telephone);
Assert.AreEqual(_webSite.Content, result.WebSite.Content);
Assert.AreEqual(_webSite.Media, result.WebSite.Media);
Assert.AreEqual(_webSite.OpenInNewWindow, result.WebSite.OpenInNewWindow);
Assert.AreEqual(_webSite.Title, result.WebSite.Title);
Assert.AreEqual(_webSite.Url, result.WebSite.Url);
}
[Test]
public void Convert_ArchetypeJson_To_AnnualStatementModel()
{
var result = ConvertArchetypeJsonToModel<AnnualStatement>(JsonTestStrings._ANNUAL_STATEMENT_JSON);
Assert.NotNull(result);
Assert.IsInstanceOf<AnnualStatement>(result);
Assert.AreEqual(new DateTime(2013, 9, 1), result.FiscalYearStart);
Assert.AreEqual(new DateTime(2014, 8, 31), result.FiscalYearEnd);
Assert.IsNull(result.DividendPaymentDate);
Assert.AreEqual(345678, result.TotalShares);
Assert.AreEqual(123456700.89, result.Sales);
Assert.AreEqual(1123456.78m, result.Profit);
}
[Test]
public void Convert_ArchetypeJson_To_AnnualStatementModel_NullableDate_HasValue()
{
var annualStatement = new AnnualStatement
{
FiscalYearStart = new DateTime(2013, 9, 1),
FiscalYearEnd = new DateTime(2014, 8, 31),
DividendPaymentDate = new DateTime(2014,9,15,10,15,30),
TotalShares = 345678,
Sales = 123456700.89,
Profit = 1123456.78m
};
var result = ConvertModelToArchetypeAndBack(annualStatement);
Assert.NotNull(result);
Assert.IsInstanceOf<AnnualStatement>(result);
Assert.AreEqual(annualStatement.FiscalYearStart, result.FiscalYearStart);
Assert.AreEqual(annualStatement.FiscalYearEnd, result.FiscalYearEnd);
Assert.AreEqual(annualStatement.DividendPaymentDate, result.DividendPaymentDate);
Assert.AreEqual(annualStatement.TotalShares, result.TotalShares);
Assert.AreEqual(annualStatement.Sales, result.Sales);
Assert.AreEqual(annualStatement.Profit, result.Profit);
}
[Test]
public void Convert_ArchetypeJson_To_AllContactDetailsModel()
{
var item1 = new ContactDetails
{
Address = "addr",
Email = "email"
};
var item2 = new ContactDetails
{
Address = "addr1",
Name = "email2"
};
var model = new AllContactDetails
{
UserDetails = item1,
AdminDetails = item2
};
var result = ConvertModelToArchetypeAndBack(model);
Assert.NotNull(result);
Assert.IsInstanceOf<AllContactDetails>(result);
Assert.AreEqual(item1.Address, result.UserDetails.Address);
Assert.AreEqual(item1.Email, result.UserDetails.Email);
Assert.AreEqual(item2.Address, result.AdminDetails.Address);
Assert.AreEqual(item2.Name, result.AdminDetails.Name);
}
[Test]
public void Convert_ArchetypeJson_To_ContactDetailsListModel()
{
var item1 = new ContactDetails
{
Address = "addr",
Email = "email"
};
var item2 = new ContactDetails
{
Address = "addr1",
Name = "email2"
};
var model = new ContactDetailsList
{
item1,
item2
};
var result = ConvertModelToArchetypeAndBack(model);
Assert.NotNull(result);
Assert.IsInstanceOf<ContactDetailsList>(result);
Assert.AreEqual(result.Count, 2);
Assert.AreEqual(item1.Address, result[0].Address);
Assert.AreEqual(item1.Email, result[0].Email);
Assert.AreEqual(item2.Address, result[1].Address);
Assert.AreEqual(item2.Name, result[1].Name);
}
[Test]
public void Convert_ArchetypeJson_To_CompanyDetailsModel()
{
var model = new CompanyDetails
{
Region = "Test Region",
ContactDetails = new ContactDetails
{
Address = "addr1",
Name = "email2"
}
};
var result = ConvertModelToArchetypeAndBack(model);
Assert.NotNull(result);
Assert.IsInstanceOf<CompanyDetails>(result);
Assert.AreEqual(model.Region, result.Region);
Assert.AreEqual(model.ContactDetails.Address, result.ContactDetails.Address);
Assert.AreEqual(model.ContactDetails.Name, result.ContactDetails.Name);
}
#endregion
}
}
@@ -1,206 +0,0 @@
using System.Linq;
using Archetype.Tests.Serialization.Base;
using Newtonsoft.Json;
using NUnit.Framework;
namespace Archetype.Tests.Serialization.UseCases.Complex
{
[TestFixture]
public class ArchetypeJsonConverterTest : ArchetypeJsonConverterTestBase
{
private TextList _textList;
private Captions _captions;
private PageDetails _pageDetails;
private SlideShow _slides;
private Seo _seo;
private TextPageList _textPages;
private PageList _pages;
[SetUp]
public void SetUp()
{
InitComplexModels();
InitComplexTreeModel();
}
#region complex nested model tests
[Test]
public void Convert_PageDetailsModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_pageDetails, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._PAGE_DETAILS_JSON, result);
}
[Test]
public void Convert_PageDetailsModel_To_Archetype()
{
Assert.NotNull(ConvertModelToArchetype(_pageDetails));
}
[Test]
public void Convert_ArchetypeJson_To_PageDetailsModel()
{
var result = ConvertArchetypeJsonToModel<PageDetails>(JsonTestStrings._PAGE_DETAILS_JSON);
Assert.NotNull(result);
Assert.IsInstanceOf<PageDetails>(result);
Assert.AreEqual("2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453", result.Pages);
Assert.AreEqual("First Page", result.Captions.TextStringArray.ElementAt(0).TextString);
Assert.AreEqual("Second Page", result.Captions.TextStringArray.ElementAt(1).TextString);
Assert.AreEqual("Third Page", result.Captions.TextStringArray.ElementAt(2).TextString);
Assert.AreEqual("Fourth Page", result.Captions.TextStringArray.ElementAt(3).TextString);
}
[Test]
public void Convert_PageDetailsModel_To_Archetype_AndBack()
{
var result = ConvertModelToArchetypeAndBack(_pageDetails);
Assert.NotNull(result);
Assert.IsInstanceOf<PageDetails>(result);
Assert.AreEqual(_pageDetails.Pages, result.Pages);
Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(0).TextString, result.Captions.TextStringArray.ElementAt(0).TextString);
Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(1).TextString, result.Captions.TextStringArray.ElementAt(1).TextString);
Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(2).TextString, result.Captions.TextStringArray.ElementAt(2).TextString);
Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(3).TextString, result.Captions.TextStringArray.ElementAt(3).TextString);
}
#endregion
#region complex nested tree model tests
[Test]
public void Convert_PagesModel_To_Archetype()
{
Assert.NotNull(ConvertModelToArchetype(_pages));
}
[Test]
public void Convert_PagesModel_To_ArchetypeJson()
{
var result = ConvertModelToArchetypeJson(_pages, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._PAGES_JSON, result);
}
[Test]
public void Convert_ArchetypeJson_To_PagesModel()
{
var result = ConvertArchetypeJsonToModel<PageList>(JsonTestStrings._PAGES_JSON);
Assert.NotNull(result);
Assert.IsInstanceOf<PageList>(result);
Assert.AreEqual("1,2,3,4,5,6,7,8", result.Pages.ElementAt(0).Media.Slides);
Assert.AreEqual("1,2,3,4,5,6,7,8", result.Pages.ElementAt(1).Media.Slides);
Assert.AreEqual("1,2,3,4,5,6,7,8", result.Pages.ElementAt(2).Media.Slides);
Assert.AreEqual("Test Meta Title", result.Pages.ElementAt(0).Seo.MetaTitle);
Assert.AreEqual("Test Meta Description", result.Pages.ElementAt(0).Seo.MetaDescription);
Assert.AreEqual("Test Meta Title", result.Pages.ElementAt(1).Seo.MetaTitle);
Assert.AreEqual("Test Meta Description", result.Pages.ElementAt(1).Seo.MetaDescription);
Assert.AreEqual("Test Meta Title", result.Pages.ElementAt(2).Seo.MetaTitle);
Assert.AreEqual("Test Meta Description", result.Pages.ElementAt(2).Seo.MetaDescription);
Assert.AreEqual("Home Page Body", result.Pages.ElementAt(0).BodyText);
Assert.AreEqual("Home Page", result.Pages.ElementAt(0).PageTitle);
Assert.AreEqual("About us Page Body", result.Pages.ElementAt(1).BodyText);
Assert.AreEqual("About us Page", result.Pages.ElementAt(1).PageTitle);
Assert.AreEqual("Contact us Page Body", result.Pages.ElementAt(2).BodyText);
Assert.AreEqual("Contact us Page", result.Pages.ElementAt(2).PageTitle);
}
[Test]
public void Convert_PagesModel_To_Archetype_AndBack()
{
var result = ConvertModelToArchetypeAndBack(_pages);
Assert.NotNull(result);
Assert.IsInstanceOf<PageList>(result);
Assert.AreEqual(_pages.Pages.ElementAt(0).Media.Slides, result.Pages.ElementAt(0).Media.Slides);
Assert.AreEqual(_pages.Pages.ElementAt(1).Media.Slides, result.Pages.ElementAt(1).Media.Slides);
Assert.AreEqual(_pages.Pages.ElementAt(2).Media.Slides, result.Pages.ElementAt(2).Media.Slides);
Assert.AreEqual(_pages.Pages.ElementAt(0).Seo.MetaTitle, result.Pages.ElementAt(0).Seo.MetaTitle);
Assert.AreEqual(_pages.Pages.ElementAt(0).Seo.MetaDescription, result.Pages.ElementAt(0).Seo.MetaDescription);
Assert.AreEqual(_pages.Pages.ElementAt(1).Seo.MetaTitle, result.Pages.ElementAt(1).Seo.MetaTitle);
Assert.AreEqual(_pages.Pages.ElementAt(1).Seo.MetaDescription, result.Pages.ElementAt(1).Seo.MetaDescription);
Assert.AreEqual(_pages.Pages.ElementAt(2).Seo.MetaTitle, result.Pages.ElementAt(2).Seo.MetaTitle);
Assert.AreEqual(_pages.Pages.ElementAt(2).Seo.MetaDescription, result.Pages.ElementAt(2).Seo.MetaDescription);
Assert.AreEqual(_pages.Pages.ElementAt(0).BodyText, result.Pages.ElementAt(0).BodyText);
Assert.AreEqual(_pages.Pages.ElementAt(0).PageTitle, result.Pages.ElementAt(0).PageTitle);
Assert.AreEqual(_pages.Pages.ElementAt(1).BodyText, result.Pages.ElementAt(1).BodyText);
Assert.AreEqual(_pages.Pages.ElementAt(1).PageTitle, result.Pages.ElementAt(1).PageTitle);
Assert.AreEqual(_pages.Pages.ElementAt(2).BodyText, result.Pages.ElementAt(2).BodyText);
Assert.AreEqual(_pages.Pages.ElementAt(2).PageTitle, result.Pages.ElementAt(2).PageTitle);
}
#endregion
#region utility methods
private void InitComplexModels()
{
_textList = new TextList
{
new TextItem{TextString = "First Page"},
new TextItem{TextString = "Second Page"},
new TextItem{TextString = "Third Page"},
new TextItem{TextString = "Fourth Page"}
};
_captions = new Captions {TextStringArray = _textList};
_pageDetails = new PageDetails
{
Captions = _captions,
Pages = "2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453"
};
}
private void InitComplexTreeModel()
{
_slides = new SlideShow{Slides = "1,2,3,4,5,6,7,8"};
_seo = new Seo{MetaDescription = "Test Meta Description", MetaTitle = "Test Meta Title"};
_textPages = new TextPageList
{
new TextPage()
{
PageTitle = "Home Page",
BodyText = "Home Page Body",
Media = _slides,
Seo = _seo
},
new TextPage()
{
PageTitle = "About us Page",
BodyText = "About us Page Body",
Media = _slides,
Seo = _seo
},
new TextPage()
{
PageTitle = "Contact us Page",
BodyText = "Contact us Page Body",
Media = _slides,
Seo = _seo
}
};
_pages = new PageList
{
Pages = _textPages
};
}
#endregion
}
}
@@ -1,92 +0,0 @@
using System.Collections.Generic;
using Archetype.Serialization;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.UseCases.Complex
{
#region complex nested model
[AsArchetype("pages")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class PageDetails
{
[JsonProperty("pages")]
public string Pages { get; set; }
[AsFieldset]
[JsonProperty("captions")]
public Captions Captions { get; set; }
}
[AsArchetype("captions")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Captions
{
[JsonProperty("captions")]
public TextList TextStringArray { get; set; }
}
[AsArchetype("textstringArray")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextList : List<TextItem>
{
}
[AsArchetype("textstringArray")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextItem
{
[JsonProperty("textstring")]
public string TextString { get; set; }
}
#endregion
#region complex nested tree model
public abstract class PageBase
{
public string PageTitle { get; set; }
public string BodyText { get; set; }
}
[AsArchetype("slideShow")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class SlideShow
{
public string Slides { get; set; }
}
[AsArchetype("seo")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Seo
{
public string MetaTitle { get; set; }
public string MetaDescription { get; set; }
}
[AsArchetype("TextPage")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextPage : PageBase
{
[AsFieldset]
public SlideShow Media { get; set; }
[AsFieldset]
public Seo Seo { get; set; }
}
[AsArchetype("TextPageList")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class TextPageList : List<TextPage>
{
}
[AsArchetype("Pages")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class PageList
{
public TextPageList Pages { get; set; }
}
#endregion
}
@@ -1,245 +0,0 @@
namespace Archetype.Tests.Serialization.UseCases.Complex
{
public class JsonTestStrings
{
public const string _PAGE_DETAILS_JSON =
@"{
""fieldsets"": [
{
""alias"": ""captions"",
""properties"": [
{
""alias"": ""captions"",
""value"": {
""fieldsets"": [
{
""alias"": ""captions"",
""properties"": [
{
""alias"": ""captions"",
""value"": {
""fieldsets"": [
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""First Page""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Second Page""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Third Page""
}
]
},
{
""alias"": ""textstringArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Fourth Page""
}
]
}
]
}
}
]
}
]
}
}
]
},
{
""alias"": ""pages"",
""properties"": [
{
""alias"": ""pages"",
""value"": ""2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453""
}
]
}
]
}";
public const string _PAGES_JSON =
@"{
""fieldsets"": [
{
""alias"": ""Pages"",
""properties"": [
{
""alias"": ""Pages"",
""value"": {
""fieldsets"": [
{
""alias"": ""TextPage"",
""properties"": [
{
""alias"": ""Media"",
""value"": {
""fieldsets"": [
{
""alias"": ""slideShow"",
""properties"": [
{
""alias"": ""Slides"",
""value"": ""1,2,3,4,5,6,7,8""
}
]
}
]
}
},
{
""alias"": ""Seo"",
""value"": {
""fieldsets"": [
{
""alias"": ""seo"",
""properties"": [
{
""alias"": ""MetaTitle"",
""value"": ""Test Meta Title""
},
{
""alias"": ""MetaDescription"",
""value"": ""Test Meta Description""
}
]
}
]
}
},
{
""alias"": ""PageTitle"",
""value"": ""Home Page""
},
{
""alias"": ""BodyText"",
""value"": ""Home Page Body""
}
]
},
{
""alias"": ""TextPage"",
""properties"": [
{
""alias"": ""Media"",
""value"": {
""fieldsets"": [
{
""alias"": ""slideShow"",
""properties"": [
{
""alias"": ""Slides"",
""value"": ""1,2,3,4,5,6,7,8""
}
]
}
]
}
},
{
""alias"": ""Seo"",
""value"": {
""fieldsets"": [
{
""alias"": ""seo"",
""properties"": [
{
""alias"": ""MetaTitle"",
""value"": ""Test Meta Title""
},
{
""alias"": ""MetaDescription"",
""value"": ""Test Meta Description""
}
]
}
]
}
},
{
""alias"": ""PageTitle"",
""value"": ""About us Page""
},
{
""alias"": ""BodyText"",
""value"": ""About us Page Body""
}
]
},
{
""alias"": ""TextPage"",
""properties"": [
{
""alias"": ""Media"",
""value"": {
""fieldsets"": [
{
""alias"": ""slideShow"",
""properties"": [
{
""alias"": ""Slides"",
""value"": ""1,2,3,4,5,6,7,8""
}
]
}
]
}
},
{
""alias"": ""Seo"",
""value"": {
""fieldsets"": [
{
""alias"": ""seo"",
""properties"": [
{
""alias"": ""MetaTitle"",
""value"": ""Test Meta Title""
},
{
""alias"": ""MetaDescription"",
""value"": ""Test Meta Description""
}
]
}
]
}
},
{
""alias"": ""PageTitle"",
""value"": ""Contact us Page""
},
{
""alias"": ""BodyText"",
""value"": ""Contact us Page Body""
}
]
}
]
}
}
]
}
]
}";
}
}
@@ -1,143 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Models;
using Archetype.PropertyConverters;
using Archetype.Tests.Serialization.Base;
using Newtonsoft.Json;
using NUnit.Framework;
namespace Archetype.Tests.Serialization.UseCases.Enumerable
{
[TestFixture]
public class ArchetypeJsonConverterTest : ArchetypeJsonConverterTestBase
{
private Feedbacks _feedbacks;
private Captions _captions;
[SetUp]
public void SetUp()
{
_feedbacks = new Feedbacks
{
new Feedback{Testimonial = "Testimonial 1"},
new Feedback{Testimonial = "Testimonial 2"},
new Feedback{Testimonial = "Testimonial 3"}
};
_captions = new Captions()
{
TextArray = new List<Text>
{
new Text{TextString = "Caption 1"},
new Text{TextString = "Caption 2"},
new Text{TextString = "Caption 3"}
}
};
}
#region Feedback - single fieldset with multiple items
[Test]
public void Convert_FeedbackModel_To_Archetype()
{
var converter = new ArchetypeValueConverter();
var json = JsonConvert.SerializeObject(_feedbacks);
var archetype = (ArchetypeModel)converter.ConvertDataToSource(null, json, false);
Assert.NotNull(archetype);
}
[Test]
public void Convert_FeedbackModel_To_ArchetypeJson()
{
var json = ConvertModelToArchetypeJson(_feedbacks, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._FEEDBACK_JSON, json);
}
[Test]
public void Convert_ArchetypeJson_To_FeedbackModel()
{
var result = ConvertArchetypeJsonToModel<Feedbacks>(JsonTestStrings._FEEDBACK_JSON);
Assert.NotNull(result);
Assert.AreEqual(3, result.Count);
foreach (var feedback in result)
{
Assert.AreEqual(String.Format("Testimonial {0}", result.IndexOf(feedback) + 1),
feedback.Testimonial);
}
}
[Test]
public void Convert_FeedbackModel_To_Archetype_AndBack()
{
var result = ConvertModelToArchetypeAndBack(_feedbacks);
Assert.NotNull(result);
Assert.AreEqual(3, result.Count);
foreach (var feedback in result)
{
var index = result.IndexOf(feedback);
Assert.AreEqual(_feedbacks.ElementAt(index).Testimonial, feedback.Testimonial);
}
}
#endregion
#region Captions - a root fieldset which contains another fieldset list
[Test]
public void Convert_CaptionsModel_To_Archetype()
{
var converter = new ArchetypeValueConverter();
var json = JsonConvert.SerializeObject(_captions);
var archetype = (ArchetypeModel)converter.ConvertDataToSource(null, json, false);
Assert.NotNull(archetype);
}
[Test]
public void Convert_CaptionsModel_To_ArchetypeJson()
{
var json = ConvertModelToArchetypeJson(_captions, Formatting.Indented);
Assert.AreEqual(JsonTestStrings._CAPTIONS_JSON, json);
}
[Test]
public void Convert_ArchetypeJson_To_CaptionsModel()
{
var result = ConvertArchetypeJsonToModel<Captions>(JsonTestStrings._CAPTIONS_JSON);
Assert.NotNull(result);
Assert.NotNull(result.TextArray);
Assert.AreEqual(3, result.TextArray.Count);
foreach (var caption in result.TextArray)
{
Assert.AreEqual(String.Format("Caption {0}", result.TextArray.IndexOf(caption) + 1),
caption.TextString);
}
}
[Test]
public void Convert_CaptionsModel_To_Archetype_AndBack()
{
var result = ConvertModelToArchetypeAndBack(_captions);
Assert.NotNull(result);
Assert.NotNull(result.TextArray);
Assert.AreEqual(3, result.TextArray.Count);
foreach (var caption in result.TextArray)
{
var index = result.TextArray.IndexOf(caption);
Assert.AreEqual(_captions.TextArray.ElementAt(index).TextString, caption.TextString);
}
}
#endregion
}
}
@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using Archetype.Serialization;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.UseCases.Enumerable
{
#region Feedback - single fieldset with multiple items
[AsArchetype("feedbacks")] /* Note: when inheriting from a list, archetype alias is not used */
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Feedbacks : List<Feedback>
{
}
[AsArchetype("feedback")] /* Must have same archetype alias as list class */
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Feedback
{
[JsonProperty("testimonial")]
public String Testimonial { get; set; }
}
#endregion
#region Captions - a root fieldset which contains another fieldset list
[AsArchetype("captions")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Captions
{
[JsonProperty("captions")]
public List<Text> TextArray { get; set; }
}
[AsArchetype("textArray")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class Text
{
[JsonProperty("textstring")]
public String TextString { get; set; }
}
#endregion
[AsArchetype("aboutUs")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class AboutUs
{
[AsFieldset]
[JsonProperty("contacts")]
public IEnumerable<ContactDetails> Contacts { get; set; }
[AsFieldset]
[JsonProperty("testimonials")]
public IEnumerable<String> Testimonials { get; set; }
}
}
@@ -1,86 +0,0 @@
namespace Archetype.Tests.Serialization.UseCases.Enumerable
{
public class JsonTestStrings
{
public const string _ABOUT_US_JSON =
@"";
public const string _FEEDBACK_JSON =
@"{
""fieldsets"": [
{
""alias"": ""feedback"",
""properties"": [
{
""alias"": ""testimonial"",
""value"": ""Testimonial 1""
}
]
},
{
""alias"": ""feedback"",
""properties"": [
{
""alias"": ""testimonial"",
""value"": ""Testimonial 2""
}
]
},
{
""alias"": ""feedback"",
""properties"": [
{
""alias"": ""testimonial"",
""value"": ""Testimonial 3""
}
]
}
]
}";
public const string _CAPTIONS_JSON =
@"{
""fieldsets"": [
{
""alias"": ""captions"",
""properties"": [
{
""alias"": ""captions"",
""value"": {
""fieldsets"": [
{
""alias"": ""textArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Caption 1""
}
]
},
{
""alias"": ""textArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Caption 2""
}
]
},
{
""alias"": ""textArray"",
""properties"": [
{
""alias"": ""textstring"",
""value"": ""Caption 3""
}
]
}
]
}
}
]
}
]
}";
}
}
@@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using Archetype.Serialization;
using Newtonsoft.Json;
namespace Archetype.Tests.Serialization.UseCases
{
#region json test Models
[AsArchetype("urlPicker")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class UrlPicker
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("content")]
public int? Content { get; set; }
[JsonProperty("media")]
public int? Media { get; set; }
[JsonProperty("openInNewWindow")]
public bool OpenInNewWindow { get; set; }
}
[AsArchetype("contactDetails")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class ContactDetails
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("address")]
public string Address { get; set; }
[JsonProperty("telephone")]
public string Telephone { get; set; }
[JsonProperty("mobile")]
public string Mobile { get; set; }
[JsonProperty("fax")]
public string Fax { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("webSite")]
public UrlPicker WebSite { get; set; }
}
[AsArchetype("companyDetails")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class CompanyDetails
{
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("contactDetails")]
public ContactDetails ContactDetails { get; set; }
}
[AsArchetype("allContactDetails")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class AllContactDetails
{
public ContactDetails UserDetails { get; set; }
public ContactDetails AdminDetails { get; set; }
}
[AsArchetype("contactDetailsList")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class ContactDetailsList : List<ContactDetails>
{
}
[AsArchetype("annualStatement")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class AnnualStatement
{
public DateTime FiscalYearStart { get; set; }
public DateTime FiscalYearEnd { get; set; }
public DateTime? DividendPaymentDate { get; set; }
public Int32 TotalShares { get; set; }
public Double Sales { get; set; }
public Decimal Profit { get; set; }
}
[AsArchetype("mergerDetails")]
[JsonConverter(typeof(ArchetypeJsonConverter))]
public class MergerDetails
{
public DateTime MergerDate { get; set; }
[JsonIgnore]
public decimal MergerValue { get; set; }
}
#endregion
}
@@ -1,207 +0,0 @@
namespace Archetype.Tests.Serialization.UseCases
{
public class JsonTestStrings
{
public const string _MERGER_DETAILS_JSON =
@"{
""fieldsets"": [
{
""alias"": ""mergerDetails"",
""properties"": [
{
""alias"": ""MergerDate"",
""value"": ""07/06/2014 08:09:10""
}
]
}
]
}";
public const string _ANNUAL_STATEMENT_JSON =
@"{
""fieldsets"": [
{
""alias"": ""annualStatement"",
""properties"": [
{
""alias"": ""FiscalYearStart"",
""value"": ""01/09/2013 00:00:00""
},
{
""alias"": ""FiscalYearEnd"",
""value"": ""31/08/2014 00:00:00""
},
{
""alias"": ""DividendPaymentDate"",
""value"": """"
},
{
""alias"": ""TotalShares"",
""value"": ""345678""
},
{
""alias"": ""Sales"",
""value"": ""123456700.89""
},
{
""alias"": ""Profit"",
""value"": ""1123456.78""
}
]
}
]
}";
public const string _CONTACT_DETAILS_JSON =
@"{
""fieldsets"": [
{
""alias"": ""contactDetails"",
""properties"": [
{
""alias"": ""name"",
""value"": ""Test""
},
{
""alias"": ""address"",
""value"": ""Test Address""
},
{
""alias"": ""telephone"",
""value"": ""111""
},
{
""alias"": ""mobile"",
""value"": ""000""
},
{
""alias"": ""fax"",
""value"": ""000""
},
{
""alias"": ""email"",
""value"": ""test@test.com""
},
{
""alias"": ""webSite"",
""value"": {
""fieldsets"": [
{
""alias"": ""urlPicker"",
""properties"": [
{
""alias"": ""title"",
""value"": ""The Test Company""
},
{
""alias"": ""url"",
""value"": ""http://test.com""
},
{
""alias"": ""content"",
""value"": """"
},
{
""alias"": ""media"",
""value"": """"
},
{
""alias"": ""openInNewWindow"",
""value"": ""1""
}
]
}
]
}
}
]
}
]
}";
public const string _COMPANY_DETAILS_JSON =
@"{
""fieldsets"": [
{
""alias"": ""companyDetails"",
""properties"": [
{
""alias"": ""region"",
""value"": ""Test Region""
},
{
""alias"": ""contactDetails"",
""value"": {
""fieldsets"": [
{
""alias"": ""contactDetails"",
""properties"": [
{
""alias"": ""name"",
""value"": ""Test""
},
{
""alias"": ""address"",
""value"": ""Test Address""
},
{
""alias"": ""telephone"",
""value"": ""111""
},
{
""alias"": ""mobile"",
""value"": ""000""
},
{
""alias"": ""fax"",
""value"": ""000""
},
{
""alias"": ""email"",
""value"": ""test@test.com""
},
{
""alias"": ""webSite"",
""value"": {
""fieldsets"": [
{
""alias"": ""urlPicker"",
""properties"": [
{
""alias"": ""title"",
""value"": ""The Test Company""
},
{
""alias"": ""url"",
""value"": ""http://test.com""
},
{
""alias"": ""content"",
""value"": """"
},
{
""alias"": ""media"",
""value"": """"
},
{
""alias"": ""openInNewWindow"",
""value"": ""1""
}
]
}
]
}
}
]
}
]
}
}
]
}
]
}";
public const string _NULL_VALUES_JSON = @"{""fieldsets"":[{""alias"":""contactDetails"",""properties"":[{""alias"":""name"",""value"":""""},{""alias"":""address"",""value"":""""},{""alias"":""telephone"",""value"":""""},{""alias"":""mobile"",""value"":""""},{""alias"":""fax"",""value"":""""},{""alias"":""email"",""value"":""""},{""alias"":""webSite"",""value"":""""}]}]}";
}
}
@@ -1,109 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<settings>
<!--
umbracoSettings.config configuration documentation can be found here:
http://our.umbraco.org/documentation/using-umbraco/config-files/umbracoSettings/
Many of the optional settings are not explicitly listed here
but can be found in the online documentation.
-->
<content>
<errors>
<error404>1</error404>
<!--
<error404>
<errorPage culture="default">1</errorPage>
<errorPage culture="en-US">200</errorPage>
</error404>
-->
</errors>
<notifications>
<!-- the email that should be used as from mail when umbraco sends a notification -->
<email>your@email.here</email>
</notifications>
<!-- Show property descriptions in editing view "icon|text|none" -->
<PropertyContextHelpOption>text</PropertyContextHelpOption>
<!-- The html injected into a (x)html page if Umbraco is running in preview mode -->
<PreviewBadge><![CDATA[<a id="umbracoPreviewBadge" style="position: absolute; top: 0; right: 0; border: 0; width: 149px; height: 149px; background: url('{1}/preview/previewModeBadge.png') no-repeat;" href="{0}/endPreview.aspx?redir={2}"><span style="display:none;">In Preview Mode - click to end</span></a>]]></PreviewBadge>
<!-- Cache cycle of Media and Member data fetched from the umbraco.library methods -->
<!-- In seconds. 0 will disable cache -->
<UmbracoLibraryCacheDuration>1800</UmbracoLibraryCacheDuration>
<!-- How Umbraco should handle errors during macro execution. Can be one of the following values:
- inline - show an inline error within the macro but allow the page to continue rendering. Historial Umbraco behaviour.
- silent - Silently suppress the error and do not render the offending macro.
- throw - Throw an exception which can be caught by the global error handler defined in Application_OnError. If no such
error handler is defined then you'll see the Yellow Screen Of Death (YSOD) error page.
Note the error can also be handled by the umbraco.macro.Error event, where you can log/alarm with your own code and change the behaviour per event. -->
<MacroErrors>inline</MacroErrors>
<!-- These file types will not be allowed to be uploaded via the upload control for media and content -->
<disallowedUploadFiles>ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd</disallowedUploadFiles>
<!-- Defines the default document type property used when adding properties in the back-office (if missing or empty, defaults to Textstring -->
<defaultDocumentTypeProperty>Textstring</defaultDocumentTypeProperty>
</content>
<security>
<!-- set to true to auto update login interval (and there by disabling the lock screen -->
<keepUserLoggedIn>false</keepUserLoggedIn>
<!-- change in 4.8: Disabled users are now showed dimmed and last in the tree. If you prefer not to display them set this to true -->
<hideDisabledUsersInBackoffice>false</hideDisabledUsersInBackoffice>
</security>
<requestHandler>
<!-- this will ensure that urls are unique when running with multiple root nodes -->
<useDomainPrefixes>false</useDomainPrefixes>
<!-- this will add a trailing slash (/) to urls when in directory url mode -->
<addTrailingSlash>true</addTrailingSlash>
</requestHandler>
<templates>
<!-- To switch the default rendering engine to MVC, change this value from WebForms to Mvc -->
<defaultRenderingEngine>Mvc</defaultRenderingEngine>
</templates>
<scheduledTasks>
<!-- add tasks that should be called with an interval (seconds) -->
<!-- <task log="true" alias="test60" interval="60" url="http://localhost/umbraco/test.aspx"/>-->
</scheduledTasks>
<!-- distributed calls make umbraco use webservices to handle cache refreshing -->
<distributedCall enable="false">
<!-- the id of the user who's making the calls -->
<!-- needed for security, umbraco will automatically look up correct login and passwords -->
<user>0</user>
<servers>
<!-- add ip number or hostname, make sure that it can be reached from all servers -->
<!-- you can also add optional attributes to force a protocol or port number (see #2) -->
<!-- <server>127.0.0.1</server>-->
<!-- <server forceProtocol="http|https" forcePortnumber="80|443">127.0.0.1</server>-->
</servers>
</distributedCall>
<!--
web.routing
@trySkipIisCustomErrors
Tries to skip IIS custom errors.
Starting with IIS 7.5, this must be set to true for Umbraco 404 pages to show. Else, IIS will take
over and render its build-in error page. See MS doc for HttpResponseBase.TrySkipIisCustomErrors.
The default value is false, for backward compatibility reasons, which means that IIS _will_ take
over, and _prevent_ Umbraco 404 pages to show.
@internalRedirectPreservesTemplate
By default as soon as we're not displaying the initial document, we reset the template set by the
finder or by the alt. template. Set this option to true to preserve the template set by the finder
or by the alt. template, in case of an internal redirect.
(false by default, and in fact should remain false unless you know what you're doing)
-->
<web.routing
trySkipIisCustomErrors="false"
internalRedirectPreservesTemplate="false">
</web.routing>
</settings>
+46 -9
View File
@@ -33,119 +33,145 @@
<ItemGroup>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="AutoMapper.Net4">
<HintPath>..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="businesslogic">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\businesslogic.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ClientDependency.Core">
<HintPath>..\packages\ClientDependency.1.7.1.2\lib\ClientDependency.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ClientDependency.Core.Mvc">
<HintPath>..\packages\ClientDependency-Mvc.1.7.0.4\lib\ClientDependency.Core.Mvc.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="cms">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\cms.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="controls">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\controls.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="CookComputing.XmlRpcV2">
<HintPath>..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Examine">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Examine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="HtmlAgilityPack">
<HintPath>..\packages\HtmlAgilityPack.1.4.6\lib\Net45\HtmlAgilityPack.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImageProcessor">
<HintPath>..\packages\ImageProcessor.1.9.0.0\lib\ImageProcessor.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="ImageProcessor.Web">
<HintPath>..\packages\ImageProcessor.Web.3.2.3.0\lib\net45\ImageProcessor.Web.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="interfaces">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="log4net">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\log4net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Lucene.Net">
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.ApplicationBlocks.Data">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Microsoft.ApplicationBlocks.Data.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Web.Helpers">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Microsoft.Web.Helpers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Mvc.FixedDisplayModes">
<HintPath>..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MiniProfiler">
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="MySql.Data">
<HintPath>..\packages\MySql.Data.6.6.5\lib\net40\MySql.Data.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.6.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SQLCE4Umbraco">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\SQLCE4Umbraco.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\System.Data.SqlServerCe.dll</HintPath>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<Private>False</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
@@ -155,36 +181,47 @@
<Reference Include="System.Xml" />
<Reference Include="TidyNet">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\TidyNet.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Core">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.DataLayer">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.DataLayer.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.editorControls">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.editorControls.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.MacroEngines">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.MacroEngines.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.providers">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.providers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Umbraco.Web.UI">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\Umbraco.Web.UI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="umbraco.XmlSerializers">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\umbraco.XmlSerializers.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UmbracoExamine">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\UmbracoExamine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UrlRewritingNet.UrlRewriter">
<HintPath>..\packages\UmbracoCms.Core.7.1.2\lib\UrlRewritingNet.UrlRewriter.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
+6
View File
@@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Tests", "Archetyp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseSizer", "DatabaseSizer\DatabaseSizer.csproj", "{0114C963-C514-49C1-B7AB-DCB1825F498C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Courier", "Archetype.Courier\Archetype.Courier.csproj", "{FE8BE437-8B11-4E49-9B02-F45994E6D723}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -32,6 +34,10 @@ Global
{0114C963-C514-49C1-B7AB-DCB1825F498C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0114C963-C514-49C1-B7AB-DCB1825F498C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0114C963-C514-49C1-B7AB-DCB1825F498C}.Release|Any CPU.Build.0 = Release|Any CPU
{FE8BE437-8B11-4E49-9B02-F45994E6D723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE8BE437-8B11-4E49-9B02-F45994E6D723}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE8BE437-8B11-4E49-9B02-F45994E6D723}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE8BE437-8B11-4E49-9B02-F45994E6D723}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -8,6 +8,9 @@ using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Umbraco.Web.Editors;
using Umbraco.Core.PropertyEditors;
using Archetype.Extensions;
using Newtonsoft.Json;
namespace Archetype.Api
{
@@ -19,7 +22,7 @@ namespace Archetype.Api
{
return
global::Umbraco.Core.PropertyEditors.PropertyEditorResolver.Current.PropertyEditors
.Select(x => new {defaultPreValues = x.DefaultPreValues, alias = x.Alias, view = x.ValueEditor.View});
.Select(x => new {defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View});
}
public object GetAll()
@@ -35,8 +38,20 @@ namespace Archetype.Api
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
return new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues };
}
public object GetByGuid(Guid guid, string contentTypeAlias, string propertyTypeAlias, string archetypeAlias, int nodeId)
{
var dataType = Services.DataTypeService.GetDataTypeDefinitionById(guid);
if (dataType == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
return new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues, contentTypeAlias = contentTypeAlias, propertyTypeAlias = propertyTypeAlias, archetypeAlias = archetypeAlias, nodeId = nodeId };
}
}
}
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
@@ -232,7 +232,10 @@
<Compile Include="Constants.cs" />
<Compile Include="Events\ExpireCache.cs" />
<Compile Include="Extensions\ArchetypeHelper.cs" />
<Compile Include="Extensions\Extensions.cs" />
<Compile Include="Extensions\HtmlHelperExtensions.cs" />
<Compile Include="Extensions\ArchetypePropertyModelExtensions.cs" />
<Compile Include="Extensions\PropertyEditorExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Models\ArchetypeModel.cs" />
<Compile Include="Models\ArchetypePreValue.cs" />
<Compile Include="Models\ArchetypePreValueFieldset.cs" />
@@ -242,12 +245,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\VersionInfo.cs" />
<Compile Include="PropertyConverters\ArchetypeValueConverter.cs" />
<Compile Include="Serialization\ArchetypeJsonDelinter.cs" />
<Compile Include="Serialization\AsArchetypeAttribute.cs" />
<Compile Include="PropertyEditors\ArchetypePropertyEditor.cs" />
<Compile Include="Serialization\ArchetypeJsonConverter.cs" />
<Compile Include="Serialization\AsFieldsetAttribute.cs" />
<Compile Include="Serialization\SerializationExtensions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@@ -3,6 +3,7 @@ using System.Linq;
using Archetype.Models;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
@@ -26,11 +27,13 @@ namespace Archetype.Extensions
_app = ApplicationContext.Current;
}
internal Models.ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues)
internal JsonSerializerSettings JsonSerializerSettings { get { return _jsonSettings; } }
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues)
{
try
{
var archetype = JsonConvert.DeserializeObject<Models.ArchetypeModel>(sourceJson, _jsonSettings);
var archetype = JsonConvert.DeserializeObject<ArchetypeModel>(sourceJson, _jsonSettings);
try
{
@@ -40,21 +43,22 @@ namespace Archetype.Extensions
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeHelper>("DeserializeJsonToArchetype", ex);
}
return archetype;
}
catch
{
return new Models.ArchetypeModel();
return new ArchetypeModel();
}
}
internal Models.ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null)
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null)
{
try
{
var archetype = JsonConvert.DeserializeObject<Models.ArchetypeModel>(sourceJson, _jsonSettings);
var archetype = JsonConvert.DeserializeObject<ArchetypeModel>(sourceJson, _jsonSettings);
try
{
@@ -64,16 +68,26 @@ namespace Archetype.Extensions
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeHelper>("DeserializeJsonToArchetype", ex);
}
return archetype;
}
catch
{
return new Models.ArchetypeModel();
return new ArchetypeModel();
}
}
internal bool IsPropertyValueConverterOverridden(int dataTypeId)
{
var prevalues = GetArchetypePreValueFromDataTypeId(dataTypeId);
if (prevalues == null)
return false;
return prevalues.OverrideDefaultPropertyValueConverter;
}
private ArchetypePreValue GetArchetypePreValueFromDataTypeId(int dataTypeId)
{
return _app.ApplicationCache.RuntimeCache.GetCacheItem(
@@ -101,7 +115,7 @@ namespace Archetype.Extensions
return preValue;
}
private IDataTypeDefinition GetDataTypeByGuid(Guid guid)
internal IDataTypeDefinition GetDataTypeByGuid(Guid guid)
{
return (IDataTypeDefinition)ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
Constants.CacheKey_DataTypeByGuid + guid,
@@ -113,7 +127,7 @@ namespace Archetype.Extensions
/// </summary>
/// <param name="archetype">The Archetype to add the additional metadata to</param>
/// <param name="preValue">The configuration of the Archetype</param>
private void RetrieveAdditionalProperties(ref Models.ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null)
private void RetrieveAdditionalProperties(ref ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null)
{
foreach (var fieldset in preValue.Fieldsets)
{
@@ -140,7 +154,7 @@ namespace Archetype.Extensions
/// </summary>
/// <param name="archetype">The Archetype to add the additional metadata to</param>
/// <param name="preValue">The configuration of the Archetype</param>
private void RetrieveAdditionalProperties(ref Models.ArchetypePreValue preValue)
private void RetrieveAdditionalProperties(ref ArchetypePreValue preValue)
{
foreach (var fieldset in preValue.Fieldsets)
{
@@ -0,0 +1,20 @@
using Archetype.Models;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
namespace Archetype.Extensions
{
public static class ArchetypePropertyModelExtensions
{
public static bool IsArchetype(this ArchetypePropertyModel prop)
{
return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias);
}
internal static PublishedPropertyType CreateDummyPropertyType(this ArchetypePropertyModel prop)
{
return new PublishedPropertyType(prop.HostContentType, new PropertyType(new DataTypeDefinition(-1, prop.PropertyEditorAlias) { Id = prop.DataTypeId }));
}
}
}
@@ -1,32 +1,14 @@
using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web;
using Archetype.Models;
using Umbraco.Core.Logging;
namespace Archetype.Extensions
{
public static class Extensions
public static class HtmlHelperExtensions
{
//lifted from the core as it is marked 'internal'
public static bool DetectIsJson(this string input)
{
input = input.Trim();
return input.StartsWith("{") && input.EndsWith("}")
|| input.StartsWith("[") && input.EndsWith("]");
}
public static bool IsArchetype(this ArchetypePropertyModel prop)
{
return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias);
}
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel)
{
return RenderPartials(htmlHelper, archetypeModel, null, null);
@@ -44,10 +26,10 @@ namespace Archetype.Extensions
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
return RenderPartials(htmlHelper, archetypeModel, partialPath, viewDataDictionary);
return htmlHelper.RenderPartials(archetypeModel, partialPath, viewDataDictionary);
}
private static IHtmlString RenderPartials(HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
private static IHtmlString RenderPartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
var context = HttpContext.Current;
@@ -57,7 +39,7 @@ namespace Archetype.Extensions
}
var sb = new StringBuilder();
var pathToPartials = "~/Views/Partials/Archetype/";
if (!string.IsNullOrEmpty(partialPath))
{
@@ -81,4 +63,4 @@ namespace Archetype.Extensions
return new HtmlString(sb.ToString());
}
}
}
}
@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core.PropertyEditors;
namespace Archetype.Extensions
{
public static class PropertyEditorExtensions
{
/// <summary>
/// Formats the default prevalues for a property editor for use within an Archetype clientside context
/// </summary>
/// <param name="propertyEditor">The property editor</param>
/// <returns>The formatted default prevalues</returns>
public static IDictionary<string, object> DefaultPreValuesForArchetype(this PropertyEditor propertyEditor)
{
if (propertyEditor.DefaultPreValues == null || propertyEditor.DefaultPreValues.Any() == false)
{
return propertyEditor.DefaultPreValues;
}
var view = propertyEditor.ValueEditor.View.ToLowerInvariant();
// This is the extension point for default prevalues formatting, in case we need to handle any other
// property editors later on. It should be replaced with a switch statement by then, or maybe some fancy
// auto discovery of formatters :)
if (view == "imagecropper")
{
propertyEditor.FormatImageCropperDefaultPreValuesForArchetype();
}
return propertyEditor.DefaultPreValues;
}
/// <summary>
/// Format the default prevalues of the image cropper property editor
/// </summary>
/// <param name="propertyEditor"></param>
/// <remarks>
/// In order for the image cropper to work clientside, we need to make sure it's default prevalue "focalpoint" is returned
/// as a JSON object and not as the string it's defined as on the image cropper property editor.
/// </remarks>
private static void FormatImageCropperDefaultPreValuesForArchetype(this PropertyEditor propertyEditor)
{
const string focalPointKey = "focalPoint";
if (propertyEditor.DefaultPreValues.ContainsKey(focalPointKey) == false || propertyEditor.DefaultPreValues[focalPointKey] == null)
{
return;
}
var focalPoint = propertyEditor.DefaultPreValues[focalPointKey].ToString();
if (string.IsNullOrEmpty(focalPoint))
{
return;
}
// translate the JSON string to a JSON object
propertyEditor.DefaultPreValues[focalPointKey] = JsonConvert.DeserializeObject(focalPoint);
}
}
}
@@ -0,0 +1,13 @@
namespace Archetype.Extensions
{
public static class StringExtensions
{
//lifted from the core as it is marked 'internal'
public static bool DetectIsJson(this string input)
{
input = input.Trim();
return input.StartsWith("{") && input.EndsWith("}")
|| input.StartsWith("[") && input.EndsWith("]");
}
}
}
@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core;
using System;
namespace Archetype.Models
{
@@ -16,6 +17,9 @@ namespace Archetype.Models
[JsonProperty("properties")]
public IEnumerable<ArchetypePropertyModel> Properties;
[JsonProperty("id")]
public Guid Id { get; set; }
public ArchetypeFieldsetModel()
{
Properties = new List<ArchetypePropertyModel>();
@@ -84,4 +88,4 @@ namespace Archetype.Models
#endregion
}
}
}
@@ -1,8 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Archetype.Serialization;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -12,7 +11,7 @@ namespace Archetype.Models
public class ArchetypeModel : IEnumerable<ArchetypeFieldsetModel>
{
[JsonProperty("fieldsets")]
internal IEnumerable<ArchetypeFieldsetModel> Fieldsets { get; set; }
public IEnumerable<ArchetypeFieldsetModel> Fieldsets { get; set; }
public ArchetypeModel()
{
@@ -29,9 +28,16 @@ namespace Archetype.Models
return this.GetEnumerator();
}
internal string SerializeForPersistence()
public string SerializeForPersistence()
{
var json = JObject.Parse(JsonConvert.SerializeObject(this));
// clear the editor state before serializing (it's temporary state data)
foreach(var property in Fieldsets.SelectMany(f => f.Properties.Where(p => p.EditorState != null)).ToList())
{
property.EditorState = null;
}
var json = JObject.Parse(JsonConvert.SerializeObject(this, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }));
var propertiesToRemove = new String[] { "propertyEditorAlias", "dataTypeId", "dataTypeGuid", "hostContentType" };
json.Descendants().OfType<JProperty>()
@@ -39,7 +45,7 @@ namespace Archetype.Models
.ToList()
.ForEach(x => x.Remove());
return json.ToString(Formatting.None).DelintArchetypeJson();
return json.ToString(Formatting.None);
}
}
}
@@ -20,6 +20,9 @@ namespace Archetype.Models
[JsonProperty("enableCollapsing")]
public bool EnableCollapsing { get; set; }
[JsonProperty("enableCloning")]
public bool EnableCloning { get; set; }
[JsonProperty("enableDisabling")]
public bool EnableDisabling { get; set; }
@@ -29,6 +32,9 @@ namespace Archetype.Models
[JsonProperty("hidePropertyLabel")]
public bool HidePropertyLabel { get; set; }
[JsonProperty("minFieldsets", NullValueHandling = NullValueHandling.Ignore)]
public int MinFieldsets { get; set; }
[JsonProperty("maxFieldsets", NullValueHandling = NullValueHandling.Ignore)]
public int MaxFieldsets { get; set; }
@@ -50,7 +56,13 @@ namespace Archetype.Models
[JsonProperty("customViewPath")]
public string CustomViewPath { get; set; }
[JsonProperty("enableDeepDatatypeRequests")]
public bool EnableDeepDatatypeRequests { get; set; }
[JsonProperty("developerMode")]
public bool DeveloperMode { get; set; }
[JsonProperty("overrideDefaultPropertyValueConverter")]
public bool OverrideDefaultPropertyValueConverter { get; set; }
}
}
@@ -1,20 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using Archetype.Extensions;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Web;
namespace Archetype.Models
{
public class ArchetypePropertyModel {
public class ArchetypePropertyModel
{
[JsonProperty("alias")]
public string Alias { get; internal set; }
public string Alias { get; set; }
[JsonProperty("value")]
public object Value { get; internal set; }
public object Value { get; set; }
[JsonProperty("propertyEditorAlias")]
public string PropertyEditorAlias { get; internal set; }
@@ -25,15 +26,18 @@ namespace Archetype.Models
[JsonProperty("dataTypeGuid")]
internal string DataTypeGuid { get; set; }
// container for temporary editor state from the Umbraco backend
[JsonProperty("editorState")]
internal UmbracoEditorState EditorState { get; set; }
[JsonProperty("hostContentType")]
internal PublishedContentType HostContentType { get; set; }
public T GetValue<T>()
{
// Try Umbraco's PropertyValueConverters
var converters = UmbracoContext.Current != null ? PropertyValueConvertersResolver.Current.Converters : Enumerable.Empty<IPropertyValueConverter>();
if (converters.Any())
if (!string.IsNullOrWhiteSpace(this.PropertyEditorAlias) && converters.Any())
{
var convertedAttempt = TryConvertWithPropertyValueConverters<T>(Value, converters);
if (convertedAttempt.Success)
@@ -54,7 +58,7 @@ namespace Archetype.Models
private Attempt<T> TryConvertWithPropertyValueConverters<T>(object value, IEnumerable<IPropertyValueConverter> converters)
{
var properyType = CreateDummyPropertyType(DataTypeId, PropertyEditorAlias);
var properyType = this.CreateDummyPropertyType();
// In umbraco, there are default value converters that try to convert the
// value if all else fails. The problem is, they are also in the list of
@@ -72,6 +76,13 @@ namespace Archetype.Models
if (value2 is T)
return Attempt<T>.Succeed((T)value2);
// If ConvertDataToSource failed try ConvertSourceToObject.
var value3 = converter.ConvertSourceToObject(properyType, value2, false);
// If the value is of type T, just return it
if (value3 is T)
return Attempt<T>.Succeed((T)value3);
// Value is not final value type, so try a regular type conversion aswell
var convertAttempt = value2.TryConvertTo<T>();
if (convertAttempt.Success)
@@ -81,13 +92,11 @@ namespace Archetype.Models
return Attempt<T>.Fail();
}
private PublishedPropertyType CreateDummyPropertyType(int dataTypeId, string propertyEditorAlias)
internal class UmbracoEditorState
{
return new PublishedPropertyType(this.HostContentType,
new PropertyType(new DataTypeDefinition(-1, propertyEditorAlias)
{
Id = dataTypeId
}));
// container for the names of any files selected for a property in the Umbraco backend
[JsonProperty("fileNames")]
public IEnumerable<string> FileNames;
}
}
}
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Imulus")]
[assembly: AssemblyProduct("Archetype")]
[assembly: AssemblyCopyright("Copyright \xa9 Imulus 2014")]
[assembly: AssemblyCopyright("MIT Licensed")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.3.0")]
[assembly: AssemblyFileVersion("1.3.0-beta")]
[assembly: AssemblyVersion("1.9")]
[assembly: AssemblyFileVersion("1.9")]
@@ -12,7 +12,6 @@ namespace Archetype.PropertyConverters
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
public class ArchetypeValueConverter : PropertyValueConverterBase
{
public ServiceContext Services
{
get { return ApplicationContext.Current.Services; }
@@ -20,8 +19,12 @@ namespace Archetype.PropertyConverters
public override bool IsConverter(PublishedPropertyType propertyType)
{
return !String.IsNullOrEmpty(propertyType.PropertyEditorAlias)
var isArcheTypePropertyEditor = !String.IsNullOrEmpty(propertyType.PropertyEditorAlias)
&& propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias);
if (!isArcheTypePropertyEditor)
return false;
return !ArchetypeHelper.Instance.IsPropertyValueConverterOverridden(propertyType.DataTypeId);
}
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
@@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Extensions;
using ClientDependency.Core;
using Newtonsoft.Json;
@@ -10,11 +11,12 @@ using Umbraco.Core.Models.Editors;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Web.PropertyEditors;
using Umbraco.Web.Models.ContentEditing;
namespace Archetype.PropertyEditors
{
[PropertyEditorAsset(ClientDependencyType.Javascript, "/App_Plugins/Archetype/js/archetype.js")]
[PropertyEditor("Imulus.Archetype", "Archetype", "/App_Plugins/Archetype/views/archetype.html", ValueType = "JSON")]
[PropertyEditorAsset(ClientDependencyType.Javascript, "../App_Plugins/Archetype/js/archetype.js")]
[PropertyEditor(Constants.PropertyEditorAlias, "Archetype", "../App_Plugins/Archetype/views/archetype.html", ValueType = "JSON")]
public class ArchetypePropertyEditor : PropertyEditor
{
#region Pre Value Editor
@@ -26,7 +28,7 @@ namespace Archetype.PropertyEditors
internal class ArchetypePreValueEditor : PreValueEditor
{
[PreValueField("archetypeConfig", "Config", "/App_Plugins/Archetype/views/archetype.config.html",
[PreValueField("archetypeConfig", "Config", "../App_Plugins/Archetype/views/archetype.config.html",
Description = "(Required) Describe your Archetype.")]
public string Config { get; set; }
@@ -49,105 +51,141 @@ namespace Archetype.PropertyEditors
protected JsonSerializerSettings _jsonSettings;
public ArchetypePropertyValueEditor(PropertyValueEditor wrapped)
: base(wrapped) { }
: base(wrapped)
{
}
public override string ConvertDbToString(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
{
if (property.Value == null || property.Value.ToString() == "")
if(property.Value == null || property.Value.ToString() == "")
return string.Empty;
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
foreach (var fieldset in archetype.Fieldsets)
{
foreach (var propDef in fieldset.Properties)
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
{
try
{
var dtd = dataTypeService.GetDataTypeDefinitionById(Guid.Parse(propDef.DataTypeGuid));
var propType = new PropertyType(dtd) { Alias = propDef.Alias };
var prop = new Property(propType, propDef.Value);
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
propDef.Value = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeHelper>(ex.Message, ex);
}
try
{
if(propDef == null || propDef.DataTypeGuid == null) continue;
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
var propType = new PropertyType(dtd) {Alias = propDef.Alias};
var prop = new Property(propType, propDef.Value);
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
propDef.Value = propEditor.ValueEditor.ConvertDbToString(prop, propType, dataTypeService);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
}
}
}
return archetype.SerializeForPersistence();
return archetype.SerializeForPersistence();
}
public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
{
if (property.Value == null || property.Value.ToString() == "")
if(property.Value == null || property.Value.ToString() == "")
return string.Empty;
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(property.Value.ToString(), propertyType.DataTypeDefinitionId);
foreach (var fieldset in archetype.Fieldsets)
{
foreach (var propDef in fieldset.Properties)
foreach (var propDef in fieldset.Properties.Where(p => p.DataTypeGuid != null))
{
try
{
var dtd = dataTypeService.GetDataTypeDefinitionById(Guid.Parse(propDef.DataTypeGuid));
var propType = new PropertyType(dtd) { Alias = propDef.Alias };
var prop = new Property(propType, propDef.Value);
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
propDef.Value = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeHelper>(ex.Message, ex);
}
try
{
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
var propType = new PropertyType(dtd) {Alias = propDef.Alias};
var prop = new Property(propType, propDef.Value);
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
propDef.Value = propEditor.ValueEditor.ConvertDbToEditor(prop, propType, dataTypeService);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
}
}
}
return archetype;
}
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue)
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue)
{
if (editorValue.Value == null || editorValue.Value.ToString() == "")
if(editorValue.Value == null || editorValue.Value.ToString() == "")
return string.Empty;
// attempt to deserialize the current property value as an Archetype
var currentArchetype = currentValue != null ? ArchetypeHelper.Instance.DeserializeJsonToArchetype(currentValue.ToString(), editorValue.PreValues) : null;
var archetype = ArchetypeHelper.Instance.DeserializeJsonToArchetype(editorValue.Value.ToString(), editorValue.PreValues);
// get all files uploaded via the file manager (if any)
var uploadedFiles = editorValue.AdditionalData.ContainsKey("files") ? editorValue.AdditionalData["files"] as IEnumerable<ContentItemFile> : null;
foreach (var fieldset in archetype.Fieldsets)
{
// assign an id to the fieldset if it has none (e.g. newly created fieldset)
fieldset.Id = fieldset.Id == Guid.Empty ? Guid.NewGuid() : fieldset.Id;
// find the corresponding fieldset in the current Archetype value (if any)
var currentFieldset = currentArchetype != null ? currentArchetype.Fieldsets.FirstOrDefault(f => f.Id == fieldset.Id) : null;
foreach (var propDef in fieldset.Properties)
{
try
{
var dtd = ApplicationContext.Current.Services.DataTypeService.GetDataTypeDefinitionById(Guid.Parse(propDef.DataTypeGuid));
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id);
var propData = new ContentPropertyData(propDef.Value, preValues, new Dictionary<string, object>());
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, propDef.Value);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeHelper>(ex.Message, ex);
}
try
{
// find the corresponding property in the current Archetype value (if any)
var currentProperty = currentFieldset != null ? currentFieldset.Properties.FirstOrDefault(p => p.Alias == propDef.Alias) : null;
var dtd = ArchetypeHelper.Instance.GetDataTypeByGuid(Guid.Parse(propDef.DataTypeGuid));
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(dtd.Id);
var additionalData = new Dictionary<string, object>();
// figure out if we need to pass a files collection in the additional data to the property value editor
if(uploadedFiles != null)
{
if(dtd.PropertyEditorAlias == Constants.PropertyEditorAlias)
{
// it's a nested Archetype - just pass all uploaded files to the value editor
additionalData["files"] = uploadedFiles.ToList();
}
else if (propDef.EditorState != null && propDef.EditorState.FileNames != null && propDef.EditorState.FileNames.Any())
{
// pass the uploaded files that belongs to this property (if any) to the value editor
var propertyFiles = propDef.EditorState.FileNames.Select(f => uploadedFiles.FirstOrDefault(u => u.FileName == f)).Where(f => f != null).ToList();
if(propertyFiles.Any())
{
additionalData["files"] = propertyFiles;
}
}
}
var propData = new ContentPropertyData(propDef.Value, preValues, additionalData);
var propEditor = PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
// make sure to send the current property value (if any) to the PE ValueEditor
propDef.Value = propEditor.ValueEditor.ConvertEditorToDb(propData, currentProperty != null ? currentProperty.Value : null);
}
catch (Exception ex)
{
LogHelper.Error<ArchetypePropertyValueEditor>(ex.Message, ex);
}
}
}
return archetype.SerializeForPersistence();
}
internal virtual PropertyEditor GetPropertyEditor(IDataTypeDefinition dtd)
{
if (dtd.Id != 0)
return PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
return dtd.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias)
? new ArchetypePropertyEditor()
: (PropertyEditor)new TextboxPropertyEditor();
}
return archetype.SerializeForPersistence();
}
internal virtual PropertyEditor GetPropertyEditor(IDataTypeDefinition dtd)
{
if(dtd.Id != 0)
return PropertyEditorResolver.Current.GetByAlias(dtd.PropertyEditorAlias);
return dtd.PropertyEditorAlias.Equals(Constants.PropertyEditorAlias)
? new ArchetypePropertyEditor()
: (PropertyEditor) new TextboxPropertyEditor();
}
}
#endregion
#endregion
}
}
@@ -1,585 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Archetype.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Archetype.Serialization
{
public class ArchetypeJsonConverter : JsonConverter
{
private const string _ROOT_FS_ALIAS = "rootFs";
#region public methods
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var models = GenerateModels(value);
if (models.Count < 1)
return;
if (models.Count == 1 && models[0] == null)
return;
var jObj = SerializeModelToFieldset(models);
writer.WriteRaw(ApplyFormatting(jObj.ToString(), writer.Formatting));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jToken = JToken.ReadFrom(reader);
if (jToken == null)
return null;
return DeserializeJson(objectType, GetDelintedJToken(jToken));
}
public override bool CanConvert(Type objectType)
{
return IsTypeArchetypeDatatype(objectType);
}
#endregion
#region private methods - deserialization
private JToken GetDelintedJToken(JToken jToken)
{
return JToken.Parse(jToken.ToString(Formatting.None).DelintArchetypeJson());
}
private object DeserializeJson(Type objectType, JToken jToken)
{
var obj = Activator.CreateInstance(objectType);
if (null != obj as IEnumerable<object>)
{
JToken enumerableToken;
if (TryParseJTokenAsEnumerable(jToken, out enumerableToken)
|| (jToken.SelectToken("value") != null && TryParseJTokenAsEnumerable(jToken["value"], out enumerableToken)))
return DeserializeEnumerableObject(obj, enumerableToken);
}
return null == jToken as JArray
? DeserializeObject(obj, jToken)
: PopulateProperties(obj, jToken);
}
private object DeserializeEnumerableObject(object obj, JToken jToken)
{
var model = obj as IEnumerable<object>;
var fsToken = jToken;
var itemType = model.GetType().GetGenericArguments().FirstOrDefault();
if (itemType == null)
{
itemType = model.GetType().BaseType.GetGenericArguments().First();
fsToken = fsToken["fieldsets"];
}
foreach (var fs in fsToken.Where(fs => fs["alias"].ToString().Equals(GetFieldsetName(itemType))))
{
var item = DeserializeJson(itemType, fs["properties"]);
obj.GetType().GetMethod("Add").Invoke(obj, new[] { item });
}
return obj;
}
private object DeserializeObject(object obj, JToken jToken)
{
if (jToken.SelectToken("value") != null
&& String.IsNullOrEmpty(jToken.SelectToken("value").ToString()))
return obj;
var properties = GetSerialiazableProperties(obj).ToList();
var asFieldset = properties.Where(HasAsFieldsetAttribute).ToList();
foreach (var propInfo in asFieldset)
{
var propAlias = GetJsonPropertyName(propInfo);
var fsJToken = propInfo.PropertyType.Namespace.Equals("System")
? GetFieldsetJTokenFromAlias(propAlias, jToken)
: GetFieldsetJTokenFromPropertyAlias(propInfo, jToken);
var propJToken = GetPropertyJToken(fsJToken, propAlias);
if (propJToken == null)
continue;
var propValue = GetPropertyValue(propInfo, propJToken);
propInfo.SetValue(obj, propValue);
}
if (properties.All(HasAsFieldsetAttribute))
return obj;
var objToken = GetFieldsetJTokenFromTypeAlias(obj.GetType(), jToken);
if (objToken == null)
return obj;
if (objToken.SelectToken("properties") != null)
return PopulateProperties(obj, objToken["properties"]);
if ((objToken is JArray) && (objToken as JArray).Count <= 0)
return null;
if (!(objToken is JArray))
return PopulateProperties(obj, new JArray(objToken));
var defaultFsProperties = properties.Where(pInfo => !HasAsFieldsetAttribute(pInfo)).ToList();
foreach (var property in defaultFsProperties)
{
var propJToken = ParseJTokenFromItems(objToken, GetJsonPropertyName(property));
PopulateProperty(obj, propJToken["properties"], property);
}
return PopulateProperties(obj, new JArray(objToken));
}
private JToken GetPropertyJToken(JToken fsJToken, string propAlias)
{
if (fsJToken == null)
return null;
//make recursive
if (fsJToken.SelectToken("properties") != null)
return GetPropertyAliasJToken(propAlias, fsJToken["properties"]);
var nestedPropJToken = fsJToken
.SingleOrDefault(p => p.SelectToken("alias").ToString().Equals(propAlias));
return nestedPropJToken != null ? GetPropertyAliasJToken(propAlias, nestedPropJToken["properties"]) : null;
}
private JToken GetFieldsetJTokenFromTypeAlias(Type objType, JToken jToken)
{
var objAlias = GetFieldsetName(objType);
return GetFieldsetJTokenFromAlias(objAlias, jToken);
}
private JToken GetFieldsetJTokenFromPropertyAlias(PropertyInfo propInfo, JToken jToken)
{
var objAlias = GetJsonPropertyName(propInfo);
return GetFieldsetJTokenFromAlias(objAlias, jToken);
}
private JToken GetFieldsetJTokenFromAlias(string objAlias, JToken jToken)
{
JToken propJToken;
if (TryParseJTokenFromNamedFieldset(jToken, objAlias, out propJToken))
return propJToken;
if (TryParseJTokenFromNestedFieldset(jToken, objAlias, out propJToken))
return propJToken;
if (TryParseJTokenFromDefaultFieldset(jToken, out propJToken))
return propJToken;
return propJToken
?? ParseJTokenFromItem(jToken, objAlias);
}
private object PopulateProperties(object obj, JToken jToken)
{
var properties = GetSerialiazableProperties(obj);
foreach (var propertyInfo in properties)
{
PopulateProperty(obj, jToken, propertyInfo);
}
return obj;
}
private void PopulateProperty(object obj, JToken jToken, PropertyInfo propertyInfo)
{
var propAlias = GetJsonPropertyName(propertyInfo);
var propJToken = GetPropertyAliasJToken(propAlias, jToken);
if (propJToken == null)
return;
var propValue = GetPropertyValue(propertyInfo, propJToken);
propertyInfo.SetValue(obj, propValue);
}
private JToken GetPropertyAliasJToken(string propAlias, JToken jToken)
{
return jToken.SingleOrDefault(p => p.SelectToken("alias").ToString().Equals(propAlias));
}
private object GetPropertyValue(PropertyInfo propertyInfo, JToken propJToken)
{
return IsTypeArchetypeDatatype(propertyInfo.PropertyType)
? DeserializeJson(propertyInfo.PropertyType, propJToken)
: IsTypeIEnumerableArchetypeDatatype(propertyInfo.PropertyType)
? DeserializeJson(propertyInfo.PropertyType, propJToken["value"].SelectToken("fieldsets"))
: GetDeserializedPropertyValue(propJToken, propertyInfo.PropertyType);
}
private JToken ParseJTokenFromItem(JToken jToken, string itemAlias)
{
return (jToken.SelectToken("alias") != null && jToken["alias"].ToString().Equals(itemAlias))
? jToken
: null;
}
private JToken ParseJTokenFromItems(JToken jToken, string itemAlias)
{
return jToken.SingleOrDefault(jT => ParseJTokenFromItem(jT, itemAlias) != null);
}
private bool TryParseJTokenFromNamedFieldset(JToken jToken, string objAlias, out JToken resultToken)
{
resultToken = null;
if (jToken.SelectToken("fieldsets") == null)
return false;
resultToken = jToken["fieldsets"].SingleOrDefault(p => p.SelectToken("alias").ToString().Equals(objAlias));
return resultToken != null;
}
private bool TryParseJTokenFromNestedFieldset(JToken jToken, string objAlias, out JToken resultToken)
{
resultToken = null;
if (jToken.SelectToken("value") == null || !jToken["value"].HasValues
|| jToken["value"]["fieldsets"] == null)
return false;
resultToken = jToken["value"]["fieldsets"].SingleOrDefault(p => p.SelectToken("alias").ToString().Equals(objAlias));
return resultToken != null;
}
private bool TryParseJTokenFromDefaultFieldset(JToken jToken, out JToken resultToken)
{
resultToken = jToken.SelectToken("fieldsets");
return resultToken != null;
}
private bool TryParseJTokenAsEnumerable(JToken jToken, out JToken resultToken)
{
resultToken = null;
//To Do: Strange newtonsoft behaviour
var fsToken = jToken.Parent != null
? jToken.Parent.Children().First() is JArray
? jToken.Parent.Children().First()
: jToken.Parent.Children().First()["fieldsets"]
: jToken.SelectToken("fieldsets");
var jTokenEnumerable = jToken != null
&& fsToken != null && fsToken is JArray;
if (jTokenEnumerable)
resultToken = jToken;
return jTokenEnumerable;
}
#endregion
#region private methods - serialization
private string ApplyFormatting(string json, Formatting formatting)
{
return JToken.Parse(json).ToString(formatting);
}
private IList GenerateModels(object value)
{
var models = value as IList;
if (null != models)
return models;
var properties = GetSerialiazableProperties(value).ToList();
if (!PropertyLayoutHasFieldsets(properties))
return new List<object>() { value };
models = new List<object>();
var fieldsetModels = properties.Where(HasAsFieldsetAttribute)
.Select(pInfo =>
{
var fsModel = GetDynamicModel(GetJsonPropertyName(pInfo));
fsModel.Add(GetJsonPropertyName(pInfo), pInfo.GetValue(value));
return fsModel;
});
models = ((IEnumerable<object>)models).Concat(fieldsetModels).ToList();
var remainingProps = properties.Where(pInfo => !HasAsFieldsetAttribute(pInfo)).ToList();
if (!remainingProps.Any())
return models;
var dynamicModel = GetDynamicModel(GetFieldsetName(value.GetType()));
foreach (var pInfo in properties.Where(pInfo => !HasAsFieldsetAttribute(pInfo)))
{
dynamicModel.Add(GetJsonPropertyName(pInfo), pInfo.GetValue(value));
}
models.Add(dynamicModel);
return models;
}
private IDictionary<string, object> GetDynamicModel(string rootFsAlias)
{
var dynamicModel = new ExpandoObject() as IDictionary<string, object>;
dynamicModel.Add(_ROOT_FS_ALIAS, rootFsAlias);
return dynamicModel;
}
private JObject SerializeModelToFieldset(IEnumerable models)
{
var jObj = new JObject
{
{
"fieldsets",
new JArray(new JRaw(SerializeModels(models)))
}
};
return jObj;
}
private IEnumerable SerializeModels(IEnumerable models)
{
var fieldsetJson = (from object model in models where null != model select SerializeModel(model)).ToList();
return String.Join(",", fieldsetJson);
}
private string SerializeModel(object value)
{
if (value == null)
return null;
var jObj = IsExpandoObject(value)
? GetJObjectFromExpandoObject(value as IDictionary<string, object>)
: GetJObject(value);
var fieldsetJson = new StringBuilder();
var fieldsetWriter = new StringWriter(fieldsetJson);
using (var jsonWriter = new JsonTextWriter(fieldsetWriter))
{
jObj.WriteTo(jsonWriter);
}
return fieldsetJson.ToString();
}
private bool PropertyLayoutHasFieldsets(IEnumerable<PropertyInfo> properties)
{
return properties.Any(HasAsFieldsetAttribute);
}
private static bool HasAsFieldsetAttribute(PropertyInfo pInfo)
{
return pInfo
.GetCustomAttributes(typeof(AsFieldsetAttribute), true).Length > 0;
}
private bool IsExpandoObject(object value)
{
return value.GetType().Name.Equals(typeof (ExpandoObject).Name);
}
private JObject GetJObjectFromExpandoObject(IDictionary<string, object> expandoObj)
{
var jObj = new JObject
{
{
"alias",
new JValue(expandoObj[_ROOT_FS_ALIAS])
}
};
var fsProperties = new List<JObject>();
foreach (var item in expandoObj.SkipWhile(i => i.Key.Equals(_ROOT_FS_ALIAS)))
{
var property = item;
var alias = property.Key;
var value = property.Value;
fsProperties.Add(new JObject
{
new JProperty("alias", alias),
new JProperty("value", value != null ? JToken.FromObject(value) : value)
});
}
jObj.Add("properties", new JRaw(JsonConvert.SerializeObject(fsProperties)));
return jObj;
}
private JObject GetJObject(object obj)
{
var jObj = new JObject
{
{
"alias",
new JValue(GetFieldsetName(obj.GetType()))
}
};
var properties = GetProperties(obj);
var fsProperties = new List<JObject>();
foreach (var propertyInfo in properties)
{
var fsProperty = new JObject();
var jProperty = new JProperty("alias", GetJsonPropertyName(propertyInfo));
fsProperty.Add(jProperty);
var propValue = propertyInfo.GetIndexParameters().Length == 0
? propertyInfo.GetValue(obj, null)
: obj as string;
fsProperty.Add(
new JProperty("value", GetJPropertyValue(propValue)));
fsProperties.Add(fsProperty);
}
jObj.Add("properties", new JRaw(JsonConvert.SerializeObject(fsProperties)));
return jObj;
}
private object GetJPropertyValue(object value)
{
return IsValueArchetypeDatatype(value)
? new JRaw(JsonConvert.SerializeObject(value))
: IsValueIEnumerableArchetypeDatatype(value)
? new JRaw(SerializeModelToFieldset(value as IEnumerable))
: new JValue(GetSerializedPropertyValue(value));
}
private IEnumerable<PropertyInfo> GetProperties(object obj)
{
if (obj.GetType() != typeof(string))
return GetSerialiazableProperties(obj);
var indexer = ((DefaultMemberAttribute)obj.GetType()
.GetCustomAttributes(typeof(DefaultMemberAttribute), true)[0]).MemberName;
return new List<PropertyInfo> { obj.GetType().GetProperty(indexer) };
}
private IEnumerable<PropertyInfo> GetSerialiazableProperties(object obj)
{
return obj.GetSerialiazableProperties();
}
private string GetJsonPropertyName(PropertyInfo property)
{
var attributes = property.GetCustomAttributes(true);
var jsonPropAttribute = (JsonPropertyAttribute)attributes.FirstOrDefault(attr => attr is JsonPropertyAttribute);
return jsonPropAttribute != null ? jsonPropAttribute.PropertyName : property.Name;
}
private string GetFieldsetName(Type type)
{
var attributes = type.GetCustomAttributes(true);
var archetypeDatatypeAttribute = (AsArchetypeAttribute)attributes.FirstOrDefault(attr => attr is AsArchetypeAttribute);
return archetypeDatatypeAttribute != null ? archetypeDatatypeAttribute.FieldsetName : type.Name;
}
private string GetSerializedPropertyValue(object propValue)
{
if (propValue == null)
return String.Empty;
if (propValue is bool)
return (bool)propValue ? GetSerializedPropertyValue(1) : GetSerializedPropertyValue(0);
return String.Format("{0}", propValue);
}
private object GetDeserializedPropertyValue(JToken jToken, Type type)
{
return String.IsNullOrEmpty(jToken.ToString())
? GetDefault(type)
: GetTypedValue(jToken, type);
}
private object GetTypedValue(JToken jToken, Type type)
{
var property = JsonConvert.DeserializeObject<ArchetypePropertyModel>(jToken.ToString());
var method = typeof(ArchetypePropertyModel).GetMethod("GetValue");
var getValue = method.MakeGenericMethod(type);
return getValue.Invoke(property, null);
}
private object GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
#endregion
#region private methods - common
private bool IsValueIEnumerableArchetypeDatatype(object value)
{
if (value as IEnumerable != null && value.GetType().IsGenericType)
return IsTypeArchetypeDatatype(value.GetType().GetGenericArguments()[0]);
return false;
}
private bool IsTypeIEnumerableArchetypeDatatype(Type type)
{
if (typeof(IEnumerable).IsAssignableFrom(type) && type.IsGenericType)
return IsTypeArchetypeDatatype(type.GetGenericArguments()[0]);
return false;
}
private bool IsValueArchetypeDatatype(object value)
{
return value != null &&
IsTypeArchetypeDatatype(value.GetType());
}
private bool IsTypeArchetypeDatatype(Type type)
{
return type.GetCustomAttributes(typeof(AsArchetypeAttribute), true).Length > 0;
}
#endregion
}
}
@@ -1,105 +0,0 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Archetype.Serialization
{
public enum DelinterStep
{
RemoveNewLine = 0,
RemoveWhiteSpace,
UnescapeLabels,
UnescapeAlias,
UnescapeValues,
FixNestedFieldsets
}
public enum DelinterAction
{
Remove = 0,
RemoveWhiteSpace,
UnescapeLabels,
UnescapeValues,
FixNestedFieldsets
}
public class ArchetypeJsonDelinter
{
public IDictionary<DelinterStep, DelinterAction> Pipeline { get; private set; }
public IDictionary<DelinterStep, Regex> Tokens { get; private set; }
public IDictionary<DelinterAction, Func<string, Regex, string>> Actions { get; private set; }
public ArchetypeJsonDelinter()
{
Init();
}
public string Execute(string input)
{
var buffer = input;
foreach (var step in Pipeline.Keys)
{
var action = Pipeline[step];
buffer = Actions[action](buffer, Tokens[step]);
}
return buffer;
}
private void Init()
{
Tokens = new Dictionary<DelinterStep, Regex>
{
{DelinterStep.RemoveNewLine, new Regex(@"(?<=\,){0,1}(\\+r\\+n)(?=\\*?""(alias|value|properties|fieldsets)\\*?"":\{*?(\\*|""|\[))|(\r|\n)+|(\\+r\\+n)(?=\s*?(\{|\}|\]))|(\\+r\\n+)(?=\s+\\*?""(alias|value|properties|fieldsets))")},
{DelinterStep.RemoveWhiteSpace, new Regex(@"(""\S+?"":)(\s+?)("")|([\{\[\}\],]|(?<!\\)"")(\s+)([\{\[\}\],]|(?<!\\)"")")},
{DelinterStep.UnescapeLabels, new Regex(@"\\+""(fieldsets|properties|alias|value)\\+"":(\s*)")},
{DelinterStep.UnescapeAlias, new Regex(@"""(alias)"":\\+""(.*?)\\+""")},
{DelinterStep.UnescapeValues, new Regex(@"""(value)"":\\+""(.*?)\\+""(?=\s*?\})")},
{DelinterStep.FixNestedFieldsets, new Regex(@"""(value)"":\s*?""\{\s*?(""fieldsets""[\S\s]+?)}""")}
};
Actions = new Dictionary<DelinterAction, Func<string, Regex, string>>
{
{DelinterAction.Remove, (input, pattern) =>
RecursiveReplace(input, pattern, match => String.Empty)
},
{DelinterAction.RemoveWhiteSpace, (input, pattern) =>
RecursiveReplace(input.Trim(), pattern, match =>
String.Format("{0}{1}{2}{3}", match.Groups[1].Value,
match.Groups[3].Value, match.Groups[4].Value, match.Groups[6].Value))
},
{DelinterAction.UnescapeLabels, (input, pattern) =>
RecursiveReplace(input, pattern, match => String.Format(@"""{0}"":", match.Groups[1].Value))
},
{DelinterAction.UnescapeValues, (input, pattern) =>
RecursiveReplace(input, pattern, match => String.Format(@"""{0}"":""{1}""", match.Groups[1].Value, match.Groups[2].Value))
},
{DelinterAction.FixNestedFieldsets, (input, pattern) =>
RecursiveReplace(input, pattern, match => String.Format(@"""{0}"":{{{1}}}", match.Groups[1].Value, match.Groups[2].Value))
}
};
Pipeline = new Dictionary<DelinterStep, DelinterAction>
{
{DelinterStep.RemoveNewLine, DelinterAction.Remove},
{DelinterStep.UnescapeLabels, DelinterAction.UnescapeLabels},
{DelinterStep.UnescapeAlias, DelinterAction.UnescapeValues},
{DelinterStep.UnescapeValues, DelinterAction.UnescapeValues},
{DelinterStep.FixNestedFieldsets, DelinterAction.FixNestedFieldsets},
{DelinterStep.RemoveWhiteSpace, DelinterAction.RemoveWhiteSpace},
};
}
private string RecursiveReplace(string input, Regex pattern, Func<Match, string> matchFunc)
{
var buffer = input;
while (pattern.IsMatch(buffer))
{
buffer = pattern.Replace(buffer, match => matchFunc(match));
}
return buffer;
}
}
}
@@ -1,14 +0,0 @@
using System;
namespace Archetype.Serialization
{
public class AsArchetypeAttribute : Attribute
{
public string FieldsetName { get; set; }
public AsArchetypeAttribute(string fieldsetname)
{
FieldsetName = fieldsetname;
}
}
}
@@ -1,8 +0,0 @@
using System;
namespace Archetype.Serialization
{
public class AsFieldsetAttribute : Attribute
{
}
}
@@ -1,53 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using Archetype.Extensions;
using Newtonsoft.Json;
using Umbraco.Core.Models;
using Umbraco.Web;
namespace Archetype.Serialization
{
public static class SerializationExtensions
{
//temporary
public static string GetPropertyDataValue(this IPublishedContent contentPage, string propertyAlias)
{
if (contentPage == null || !contentPage.HasProperty(propertyAlias))
return null;
return (string)contentPage.Properties.Single(p => p.PropertyTypeAlias == propertyAlias).DataValue;
}
public static IEnumerable<PropertyInfo> GetSerialiazableProperties(this object obj)
{
if (obj == null)
return new List<PropertyInfo>();
return obj.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(prop => !Attribute.IsDefined(prop, typeof(JsonIgnoreAttribute)));
}
public static T GetModelFromArchetype<T>(this IPublishedContent content,
string cmsFieldAlias, bool returnInstanceIfNull = false)
where T : class, new()
{
var archetypeJson = content.GetPropertyDataValue(cmsFieldAlias);
return JsonConvert.DeserializeObject<T>(archetypeJson) ??
(returnInstanceIfNull ? Activator.CreateInstance<T>() : default(T));
}
public static string DelintArchetypeJson(this string input)
{
if (!input.DetectIsJson())
return String.Empty;
var delinter = new ArchetypeJsonDelinter();
return delinter.Execute(input);
}
}
}
+3 -3
View File
@@ -6,7 +6,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
//define empty items
var newPropertyModel = '{"alias": "", "remove": false, "collapse": false, "label": "", "helpText": "", "dataTypeGuid": "0cc0eba1-9960-42c9-bf9b-60e150b429ae", "value": ""}';
var newFieldsetModel = '{"alias": "", "remove": false, "collapse": false, "labelTemplate": "", "icon": "", "label": "", "properties": [' + newPropertyModel + ']}';
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "maxFieldsets": null, "enableCollapsing": true, "enableDisabling": true, "fieldsets": [' + newFieldsetModel + ']}');
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "minFieldsets": null, "maxFieldsets": null, "enableCollapsing": true, "enableCloning": false, "enableDisabling": true, "enableDeepDatatypeRequests": false, "fieldsets": [' + newFieldsetModel + ']}');
//ini the model
$scope.model.value = $scope.model.value || defaultFieldsetConfigModel;
@@ -104,7 +104,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
//ini the properties
_.each($scope.archetypeConfigRenderModel.fieldsets, function(fieldset){
$scope.focusProperty(fieldset.properties);
$scope.focusProperty(fieldset.properties);
});
//setup JSON.stringify helpers
@@ -290,5 +290,5 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
}
//archetype css
assetsService.loadCss("/App_Plugins/Archetype/css/archetype.css");
assetsService.loadCss("../App_Plugins/Archetype/css/archetype.css");
});
+128 -31
View File
@@ -1,4 +1,4 @@
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout) {
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
//$scope.model.value = "";
$scope.model.hideLabel = $scope.model.config.hideLabel == 1;
@@ -17,49 +17,66 @@
init();
//hold references to helper resources
$scope.resources = {
entityResource: entityResource,
archetypePropertyEditorResource: archetypePropertyEditorResource
}
//hold references to helper services
$scope.services = {
archetypeService: archetypeService,
archetypeLabelService: archetypeLabelService,
archetypeCacheService: archetypeCacheService
}
//helper to get $eval the labelTemplate
$scope.getFieldsetTitle = function(fieldsetConfigModel, fieldsetIndex) {
if(!fieldsetConfigModel)
return "";
var fieldset = $scope.model.value.fieldsets[fieldsetIndex];
var fieldsetConfig = $scope.getConfigFieldsetByAlias(fieldset.alias);
var template = fieldsetConfigModel.labelTemplate;
$scope.getFieldsetTitle = function (fieldsetConfigModel, fieldsetIndex) {
return archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex);
}
if (template.length < 1)
return fieldsetConfig.label;
var rgx = /{{(.*?)}}*/g;
var results;
var parsedTemplate = template;
while ((results = rgx.exec(template)) !== null) {
var propertyAlias = results[1];
var propertyValue = $scope.getPropertyValueByAlias(fieldset, propertyAlias);
parsedTemplate = parsedTemplate.replace(results[0], propertyValue);
}
return parsedTemplate;
};
var draggedRteSettings;
var rteClass = ".mce-tinymce";
//sort config
$scope.sortableOptions = {
axis: 'y',
cursor: "move",
handle: ".handle",
start: function(ev, ui) {
draggedRteSettings = {};
ui.item.parent().find(rteClass).each(function () {
// remove all RTEs in the dragged row and save their settings
var $element = $(this);
var wrapperId = $element.attr('id');
var $textarea = $element.siblings('textarea');
var textareaId = $textarea.attr('id');
draggedRteSettings[textareaId] = _.findWhere(tinyMCE.editors, { id: textareaId }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, wrapperId);
});
},
update: function (ev, ui) {
$scope.setDirty();
},
stop: function (ev, ui) {
ui.item.parent().find(rteClass).each(function () {
var $element = $(this);
var wrapperId = $element.attr('id');
var $textarea = $element.siblings('textarea');
var textareaId = $textarea.attr('id');
draggedRteSettings[textareaId] = draggedRteSettings[textareaId] || _.findWhere(tinyMCE.editors, { id: textareaId }).settings;
tinyMCE.execCommand('mceRemoveEditor', false, wrapperId);
tinyMCE.init(draggedRteSettings[textareaId]);
});
}
};
//handles a fieldset add
$scope.addRow = function (fieldsetAlias, $index) {
if ($scope.canAdd())
{
if ($scope.model.config.fieldsets)
{
if ($scope.canAdd()) {
if ($scope.model.config.fieldsets) {
var newFieldset = getEmptyRenderFieldset($scope.getConfigFieldsetByAlias(fieldsetAlias));
if (typeof $index != 'undefined')
@@ -71,8 +88,11 @@
$scope.model.value.fieldsets.push(newFieldset);
}
}
$scope.setDirty();
$scope.$broadcast("archetypeAddFieldset", {index: $index, visible: countVisible()});
newFieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
$scope.focusFieldset(newFieldset);
}
@@ -83,6 +103,23 @@
if (confirm('Are you sure you want to remove this?')) {
$scope.setDirty();
$scope.model.value.fieldsets.splice($index, 1);
$scope.$broadcast("archetypeRemoveFieldset", {index: $index, visible: countVisible()});
}
}
}
$scope.cloneRow = function ($index) {
if ($scope.canClone() && typeof $index != 'undefined') {
var newFieldset = angular.copy($scope.model.value.fieldsets[$index]);
if(newFieldset) {
$scope.model.value.fieldsets.splice($index + 1, 0, newFieldset);
$scope.setDirty();
newFieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
$scope.focusFieldset(newFieldset);
}
}
}
@@ -94,8 +131,7 @@
}
//helpers for determining if a user can do something
$scope.canAdd = function ()
{
$scope.canAdd = function () {
if ($scope.model.config.maxFieldsets)
{
return countVisible() < $scope.model.config.maxFieldsets;
@@ -105,13 +141,26 @@
}
//helper that returns if an item can be removed
$scope.canRemove = function ()
{
$scope.canRemove = function () {
return countVisible() > 1
|| ($scope.model.config.maxFieldsets == 1 && $scope.model.config.fieldsets.length > 1)
|| $scope.model.config.startWithAddButton;
}
$scope.canClone = function () {
if (!$scope.model.config.enableCloning) {
return false;
}
if ($scope.model.config.maxFieldsets)
{
return countVisible() < $scope.model.config.maxFieldsets;
}
return true;
}
//helper that returns if an item can be sorted
$scope.canSort = function ()
{
@@ -206,11 +255,36 @@
//developerMode helpers
$scope.model.value.toString = stringify;
// issue 114: register handler for file selection
$scope.model.value.setFiles = setFiles;
//encapsulate stringify (should be built into browsers, not sure of IE support)
function stringify() {
return JSON.stringify(this);
}
// issue 114: handler for file selection
function setFiles(files) {
// get all currently selected files from file manager
var currentFiles = fileManager.getFiles();
// get the files already selected for this archetype (by alias)
var archetypeFiles = [];
_.each(currentFiles, function (item) {
if (item.alias === $scope.model.alias) {
archetypeFiles.push(item.file);
}
});
// add the newly selected files
_.each(files, function (file) {
archetypeFiles.push(file);
});
// update the selected files for this archetype (by alias)
fileManager.setFiles($scope.model.alias, archetypeFiles);
}
//watch for changes
$scope.$watch('model.value', function (v) {
if ($scope.model.config.developerMode) {
@@ -220,6 +294,13 @@
$scope.model.value.toString = stringify;
}
}
// issue 114: re-register handler for files selection and reset the currently selected files on the file manager
$scope.model.value.setFiles = setFiles;
fileManager.setFiles($scope.model.alias, []);
// reset submit watcher counter on save
$scope.activeSubmitWatcher = 0;
});
//helper to count what is visible
@@ -286,6 +367,7 @@
// recursive validation of nested fieldsets
var nestedFieldsetsValid = true;
_.each(fieldset.properties, function (property) {
if (property != null && property.value != null && property.propertyEditorAlias == "Imulus.Archetype") {
_.each(property.value.fieldsets, function (inner) {
@@ -312,11 +394,26 @@
}
//archetype css
assetsService.loadCss("/App_Plugins/Archetype/css/archetype.css");
assetsService.loadCss("../App_Plugins/Archetype/css/archetype.css");
//custom css
if($scope.model.config.customCssPath)
{
assetsService.loadCss($scope.model.config.customCssPath);
}
// submit watcher handling:
// because some property editors use the "formSubmitting" event to set/clean up their model.value,
// we need to monitor the "formSubmitting" event from a custom property and broadcast our own event
// to forcefully update the appropriate model.value's
$scope.activeSubmitWatcher = 0;
$scope.submitWatcherOnLoad = function () {
$scope.activeSubmitWatcher++;
return $scope.activeSubmitWatcher;
}
$scope.submitWatcherOnSubmit = function () {
$scope.$broadcast("archetypeFormSubmitting");
}
});
@@ -12,7 +12,7 @@ angular.module("umbraco.directives").directive('archetypeLocalize', function (ar
return {
restrict: "E",
rep1ace: true,
replace: true,
link: linker,
scope: {
key: '@'
+2 -2
View File
@@ -3,10 +3,10 @@ angular.module("umbraco.directives").directive('archetypeCustomView', function (
var view = "/App_plugins/Archetype/views/archetype.default.html";
if(scope.model.config.customViewPath) {
view = config.customViewPath;
view = scope.model.config.customViewPath;
}
$http.get(view).then(function(data) {
$http.get(view, { cache: true }).then(function(data) {
element.html(data.data).show();
+119 -156
View File
@@ -1,79 +1,33 @@
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q) {
function getFieldsetByAlias(fieldsets, alias)
{
return _.find(fieldsets, function(fieldset){
return fieldset.alias == alias;
});
}
function getPropertyIndexByAlias(properties, alias){
for (var i in properties)
{
if (properties[i].alias == alias) {
return i;
}
}
}
function getPropertyByAlias(fieldset, alias){
return _.find(fieldset.properties, function(property){
return property.alias == alias;
});
}
//helper that returns a JS ojbect from 'value' string or the original string
function jsonOrString(value, developerMode, debugLabel){
if(value && typeof value == 'string'){
try{
if(developerMode == '1'){
console.log("Trying to parse " + debugLabel + ": " + value);
}
value = JSON.parse(value);
}
catch(exception)
{
if(developerMode == '1'){
console.log("Failed to parse " + debugLabel + ".");
}
}
}
if(value && developerMode == '1'){
console.log(debugLabel + " post-parsing: ");
console.log(value);
}
return value;
}
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService, archetypeCacheService, notificationsService) {
var linker = function (scope, element, attrs, ngModelCtrl) {
var configFieldsetModel = getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
var configFieldsetModel = archetypeService.getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
var view = "";
var label = configFieldsetModel.properties[scope.propertyConfigIndex].label;
var dataTypeGuid = configFieldsetModel.properties[scope.propertyConfigIndex].dataTypeGuid;
var config = null;
var alias = configFieldsetModel.properties[scope.propertyConfigIndex].alias;
var defaultValue = configFieldsetModel.properties[scope.propertyConfigIndex].value;
var propertyAlias = getUniquePropertyAlias(scope);
propertyAliasParts = [];
// initialize container for invalid fieldset property identifiers (store on ngModelCtrl to separate Archetype validations, e.g. when there two Archetype properties on the same document)
if(ngModelCtrl.invalidProperties == null) {
ngModelCtrl.invalidProperties = [];
}
var propertyAliasParts = [];
var propertyAlias = archetypeService.getUniquePropertyAlias(scope, propertyAliasParts);
//try to convert the defaultValue to a JS object
defaultValue = jsonOrString(defaultValue, scope.archetypeConfig.developerMode, "defaultValue");
defaultValue = archetypeService.jsonOrString(defaultValue, scope.archetypeConfig.developerMode, "defaultValue");
//grab info for the selected datatype, prepare for view
archetypePropertyEditorResource.getDataType(dataTypeGuid).then(function (data) {
archetypePropertyEditorResource.getDataType(dataTypeGuid, scope.archetypeConfig.enableDeepDatatypeRequests, editorState.current.contentTypeAlias, scope.propertyEditorAlias, alias, editorState.current.id).then(function (data) {
//transform preValues array into object expected by propertyeditor views
var configObj = {};
_.each(data.preValues, function(p) {
configObj[p.key] = p.value;
});
config = configObj;
//caching for use by label templates later
archetypeCacheService.addDatatypeToCache(data, dataTypeGuid);
//determine the view to use [...] and load it
archetypePropertyEditorResource.getPropertyEditorMapping(data.selectedEditor).then(function(propertyEditor) {
var pathToView = umbPropEditorHelper.getViewPath(propertyEditor.view);
@@ -86,100 +40,15 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
var mergedConfig = _.extend(defaultConfigObj, config);
loadView(pathToView, mergedConfig, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, validateProperty);
loadView(pathToView, mergedConfig, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, configFieldsetModel);
});
});
scope.$on("formSubmitting", function (ev, args) {
// "hard" validate to highlight any erroneous entries
_.each(scope.fieldset.properties, function (property) {
validateProperty(scope.fieldset, property, true);
});
});
scope.$on("formSubmitted", function (ev, args) {
// reset the nested fieldset validation state after submit
ngModelCtrl.invalidProperties = [];
});
// need to pass the property fieldset here to clear any invalid state of the fieldset when validating a single fieldset property
// - it's the Umbraco way to hide the invalid state when altering an invalid property, even if the new value isn't valid either
function validateProperty(fieldset, property, markAsInvalid) {
var valid = true;
fieldset.isValid = true;
property.isValid = true;
var propertyConfig = getPropertyByAlias(configFieldsetModel, property.alias);
if (propertyConfig) {
// use property.value !== property.value to check for NaN values on numeric inputs
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
valid = false;
}
// issue 116: RegEx validate property value
// Only validate the property value if anything has been entered - RegEx is considered a supplement to "required".
if (valid == true && propertyConfig.regEx && property.value) {
var regEx = new RegExp(propertyConfig.regEx);
if (regEx.test(property.value) == false) {
valid = false;
}
}
// only mark the property as invalid when doing a "hard" validation
if (valid == false && markAsInvalid == true) {
property.isValid = false;
}
}
// handle nested fieldset validation by storing the identifier of all invalid fieldset properties
var fieldsetIdentifier = scope.umbracoPropertyAlias + "_" + scope.fieldsetIndex;
var propertyIdentifier = fieldsetIdentifier + "_" + property.alias;
var propertyIdentifierIndex = ngModelCtrl.invalidProperties.indexOf(propertyIdentifier);
if (valid == false) {
if (propertyIdentifierIndex == -1) {
ngModelCtrl.invalidProperties.push(propertyIdentifier);
}
}
else {
if (propertyIdentifierIndex != -1) {
ngModelCtrl.invalidProperties.splice(propertyIdentifierIndex, 1);
}
}
if (markAsInvalid) {
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
fieldset.isValid =
_.find(ngModelCtrl.invalidProperties, function (item) {
return item.indexOf(fieldsetIdentifier) == 0
}) == null;
}
// set invalid state if one or more fieldsets contain invalid properties
ngModelCtrl.$setValidity('validation', ngModelCtrl.invalidProperties.length == 0);
}
}
var propertyAliasParts = [];
var getUniquePropertyAlias = function (currentScope) {
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
{
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
propertyAliasParts.push(currentPropertyAlias);
}
else if (currentScope.hasOwnProperty('isPreValue')) // Crappy way to identify this is the umbraco property scope
{
var umbracoPropertyAlias = currentScope.$parent.$parent.property.alias; // Crappy way to get the umbraco host alias once we identify its scope
propertyAliasParts.push(umbracoPropertyAlias);
}
if (currentScope.$parent)
getUniquePropertyAlias(currentScope.$parent);
return _.unique(propertyAliasParts).reverse().join("-");
};
function loadView(view, config, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, validateProperty) {
function loadView(view, config, defaultValue, alias, propertyAlias, scope, element, ngModelCtrl, configFieldsetModel) {
if (view)
{
$http.get(view).success(function (data) {
$http.get(view, { cache: true }).success(function (data) {
if (data) {
if (scope.archetypeConfig.developerMode == '1')
{
@@ -192,28 +61,121 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
scope.model.config = {};
//ini the property value after test to make sure a prop exists in the renderModel
var renderModelPropertyIndex = getPropertyIndexByAlias(scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties, alias);
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
if (!renderModelPropertyIndex)
if (!scope.renderModelPropertyIndex)
{
scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
renderModelPropertyIndex = getPropertyIndexByAlias(scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties, alias);
archetypeService.getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
}
scope.model.value = scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties[renderModelPropertyIndex].value;
scope.renderModel = {};
scope.model.value = archetypeService.getFieldsetProperty(scope).value;
//init the property editor state
archetypeService.getFieldsetProperty(scope).editorState = {};
//set the config from the prevalues
scope.model.config = config;
/*
Property Specific Hacks
Preference is to not do these, but unless we figure out core issues, this is quickest fix.
*/
//MNTP *single* hack
if(scope.model.config.maxNumber && scope.model.config.multiPicker)
{
if(scope.model.config.maxNumber == "1")
{
scope.model.config.multiPicker = "0";
}
}
//upload datatype hack
if(view.indexOf('fileupload.html') != -1) {
scope.propertyForm = scope.form;
scope.model.validation = {};
scope.model.validation.mandatory = 0;
}
//some items need an alias
scope.model.alias = "archetype-property-" + propertyAlias;
//some items also need an id (file upload for example)
scope.model.id = propertyAlias;
//watch for changes since there is no two-way binding with the local model.value
scope.$watch('model.value', function (newValue, oldValue) {
scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties[renderModelPropertyIndex].value = newValue;
archetypeService.getFieldsetProperty(scope).value = newValue;
// call validation method for the property when the value changes
// use "soft" validation to mimic the default umbraco validation style (show error highlights on submit, not while entering data)
validateProperty(scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex], scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex].properties[renderModelPropertyIndex], false);
// notify the linker that the property value changed
archetypeService.propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
});
scope.$on('formSubmitting', function(ev, args){
archetypeCacheService.clearInvalidations();
archetypeCacheService.clearNotifications();
});
scope.$on('archetypeFormSubmitting', function (ev, args) {
// validate all fieldset properties
_.each(scope.fieldset.properties, function (property) {
archetypeService.validateProperty(scope.fieldset, property, configFieldsetModel);
});
var validationKey = "validation-f" + scope.fieldsetIndex;
ngModelCtrl.$setValidity(validationKey, scope.fieldset.isValid);
// did the value change (if it did, it most likely did so during the "formSubmitting" event)
var property = archetypeService.getFieldsetProperty(scope);
var currentValue = property.value;
if (currentValue != scope.model.value) {
archetypeService.getFieldsetProperty(scope).value = scope.model.value;
// notify the linker that the property value changed
archetypeService.propertyValueChanged(archetypeService.getFieldset(scope), archetypeService.getFieldsetProperty(scope));
}
archetypeService.validateMinFieldsets(scope);
archetypeCacheService.notifyEditor();
});
// issue 114: handle file selection on property editors
scope.$on("filesSelected", function (event, args) {
// populate the fileNames collection on the property editor state
var property = archetypeService.getFieldsetProperty(scope);
property.editorState.fileNames = [];
_.each(args.files, function (item) {
property.editorState.fileNames.push(item.name);
});
// remove the files set for this property
// NOTE: we can't use property.alias because the file manager registers the selected files on the assigned Archetype property alias (e.g. "archetype-property-archetype-property-archetype-property-content-0-2-0-1-0-0")
fileManager.setFiles(scope.model.alias, []);
// now tell the containing Archetype to pick up the selected files
scope.archetypeRenderModel.setFiles(args.files);
});
scope.$on("archetypeRemoveFieldset", function (ev, args) {
var validationKey = "validation-f" + args.index;
ngModelCtrl.$setValidity(validationKey, true);
scope.archetypeRenderModel.fieldsets.length = args.visible;
archetypeService.validateMinFieldsets(scope);
});
scope.$on("archetypeAddFieldset", function (ev, args) {
archetypeService.validateMinFieldsets(scope);
});
element.html(data).show();
@@ -237,6 +199,7 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
scope: {
property: '=',
propertyConfigIndex: '=',
propertyEditorAlias: '=',
archetypeConfig: '=',
fieldset: '=',
fieldsetIndex: '=',
@@ -245,4 +208,4 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
umbracoForm: '='
}
}
});
});
+24
View File
@@ -0,0 +1,24 @@
angular.module("umbraco.directives").directive('archetypeSubmitWatcher', function ($rootScope) {
var linker = function (scope, element, attrs, ngModelCtrl) {
// call the load callback on scope to obtain the ID of this submit watcher
var id = scope.loadCallback();
scope.$on("formSubmitting", function (ev, args) {
// on the "formSubmitting" event, call the submit callback on scope to notify the Archetype controller to do it's magic
if (id == scope.activeSubmitWatcher) {
scope.submitCallback();
}
});
}
return {
restrict: "E",
replace: true,
link: linker,
template: "",
scope: {
loadCallback: '=',
submitCallback: '=',
activeSubmitWatcher: '='
}
}
});
+70
View File
@@ -0,0 +1,70 @@
var ArchetypeSampleLabelTemplates = (function() {
//public functions
return {
Entity: function (value, scope, args) {
if(!args.entityType) {
args = {entityType: "Document", propertyName: "name"}
}
if (value) {
//if handed a csv list, take the first only
var id = value.split(",")[0];
if (id) {
var entity = scope.services.archetypeLabelService.getEntityById(scope, id, args.entityType);
if(entity) {
return entity[args.propertyName];
}
}
}
return "";
},
UrlPicker: function(value, scope, args) {
if(!args.propertyName) {
args = {propertyName: "name"}
}
var entity;
switch (value.type) {
case "content":
if(value.typeData.contentId) {
entity = scope.services.archetypeLabelService.getEntityById(scope, value.typeData.contentId, "Document");
}
break;
case "media":
if(value.typeData.mediaId) {
entity = scope.services.archetypeLabelService.getEntityById(scope, value.typeData.mediaId, "Media");
}
break;
case "url":
return value.typeData.url;
default:
break;
}
if(entity) {
return entity[args.propertyName];
}
return "";
},
Rte: function (value, scope, args) {
if(!args.contentLength) {
args = {contentLength: 50}
}
return $(value).text().substring(0, args.contentLength);
}
}
})();
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Vælg",
"icon": "Ikon",
"enableDisabling": "Aktivér fieldset-deaktivering?",
"enableDisablingDescription": "Tillad brugere at aktivere/deaktivere individuelle fieldsets."
"enableDisablingDescription": "Tillad brugere at aktivere/deaktivere individuelle fieldsets.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+43
View File
@@ -0,0 +1,43 @@
{
"label": "Label",
"alias": "Alias",
"hideFieldsetControls": "Skjul fieldsets?",
"hideFieldsetControlsDescription": "Skjuler kontrollerne tilføj/fjern/sortér.",
"toggleAdvanced": "Slå avancerede muligheder til/fra",
"toggleAdvancedDescription": "Vis avancerede muligheder.",
"hidePropertyLabels": "Skjul labels på egenskaber?",
"hidePropertyLabelsDescription": "Skjuler labels på egenskaber.",
"maxFieldsets": "Maks antal fieldsets",
"maxFieldsetsDescription": "Hvor mange fieldsets er tilladt? Hvis der skrives '1' vil deaktivere kontrollerne. Som standard er det ubegrænset.",
"enableMultipleFieldsets": "Aktivér flere Fieldsets?",
"enableMultipleFieldsetsDescription": "Tillader flere typer af fieldsets i denne archetype.",
"hideFieldsetToolbar": "Skjul Fieldset værktøjslinie?",
"hideFieldsetToolbarDescription": "Skjuler den fieldset værktøjslinie der fremkommer når der findes mere end ét fieldset.",
"customWrapperClass": "Egen Wrapper Class",
"customWrapperClassDescription": "(Mulighed) Angiv din egen CSS class som tilføjes på wrapper div'en.",
"cssFile": "CSS fil",
"cssFileDescription": "(Mulighed) Tilføj en sti til din egen CSS fil der skal inkluderes på siden.",
"jsFile": "JavaScript fil",
"jsFileDescription": "(Mulighed) Tilføj en sti til din egen JavaScript fil der skal inkluderes på siden.",
"toggleDeveloperMode": "Slå udvikler muligheder til/fra.",
"toggleDeveloperModeDescription": "Aktivér på udvikler muligheder.",
"configModel": "Konfigurationsmodel",
"configModelDescription": "Vær forsigt med at redigere teksten for neden, den kontrollerer skemaet for denne archetype.",
"helpText": "Hjælpe tekst",
"defaultValue": "Standard værdi",
"dataType": "Datatype",
"required": "Påkrævet",
"regEx": "RegEx validering",
"properties": "Egenskaber",
"labelTemplate": "Label skabelon",
"select": "Vælg",
"icon": "Ikon",
"enableDisabling": "Aktivér fieldset-deaktivering?",
"enableDisablingDescription": "Tillad brugere at aktivere/deaktivere individuelle fieldsets.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+43
View File
@@ -0,0 +1,43 @@
{
"label": "Label",
"alias": "Alias",
"hideFieldsetControls": "Hide Fieldset Controls?",
"hideFieldsetControlsDescription": "Hides the fieldset add/remove/sort controls.",
"toggleAdvanced": "Toggle Advanced Options",
"toggleAdvancedDescription": "Show advanced options.",
"hidePropertyLabels": "Hide Property Labels?",
"hidePropertyLabelsDescription": "Hides the property labels.",
"maxFieldsets": "Max Fieldsets",
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
"customWrapperClass": "Custom Wrapper Class",
"customWrapperClassDescription": "(Optional) Enter a custom CSS class that will be applied to the wrapper div.",
"cssFile": "CSS File",
"cssFileDescription": "(Optional) Enter a path for a custom CSS file to be included on the page.",
"jsFile": "JS File",
"jsFileDescription": "(Optional) Enter a path for a custom JS file to be included on the page.",
"toggleDeveloperMode": "Toggle Developer Mode",
"toggleDeveloperModeDescription": "Turn on for developer options.",
"configModel": "Config Model",
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
"required": "Required",
"regEx": "RegEx Validation",
"properties": "Properties",
"labelTemplate": "Label Template",
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+8 -1
View File
@@ -7,6 +7,7 @@
"toggleAdvancedDescription": "Show advanced options.",
"hidePropertyLabels": "Hide Property Labels?",
"hidePropertyLabelsDescription": "Hides the property labels.",
"minFieldsets": "Min Fieldsets",
"maxFieldsets": "Max Fieldsets",
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
@@ -33,5 +34,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+8 -1
View File
@@ -7,6 +7,7 @@
"toggleAdvancedDescription": "Show advanced options.",
"hidePropertyLabels": "Hide Property Labels?",
"hidePropertyLabelsDescription": "Hides the property labels.",
"minFieldsets": "Min Fieldsets",
"maxFieldsets": "Max Fieldsets",
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
@@ -33,5 +34,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+44
View File
@@ -0,0 +1,44 @@
{
"label": "Label",
"alias": "Alias",
"hideFieldsetControls": "Hide Fieldset Controls?",
"hideFieldsetControlsDescription": "Hides the fieldset add/remove/sort controls.",
"toggleAdvanced": "Toggle Advanced Options",
"toggleAdvancedDescription": "Show advanced options.",
"hidePropertyLabels": "Hide Property Labels?",
"hidePropertyLabelsDescription": "Hides the property labels.",
"minFieldsets": "Min Fieldsets",
"maxFieldsets": "Max Fieldsets",
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
"customWrapperClass": "Custom Wrapper Class",
"customWrapperClassDescription": "(Optional) Enter a custom CSS class that will be applied to the wrapper div.",
"cssFile": "CSS File",
"cssFileDescription": "(Optional) Enter a path for a custom CSS file to be included on the page.",
"jsFile": "JS File",
"jsFileDescription": "(Optional) Enter a path for a custom JS file to be included on the page.",
"toggleDeveloperMode": "Toggle Developer Mode",
"toggleDeveloperModeDescription": "Turn on for developer options.",
"configModel": "Config Model",
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
"required": "Required",
"regEx": "RegEx Validation",
"properties": "Properties",
"labelTemplate": "Label Template",
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+43
View File
@@ -0,0 +1,43 @@
{
"label": "Label",
"alias": "Alias",
"hideFieldsetControls": "Hide Fieldset Controls?",
"hideFieldsetControlsDescription": "Hides the fieldset add/remove/sort controls.",
"toggleAdvanced": "Toggle Advanced Options",
"toggleAdvancedDescription": "Show advanced options.",
"hidePropertyLabels": "Hide Property Labels?",
"hidePropertyLabelsDescription": "Hides the property labels.",
"maxFieldsets": "Max Fieldsets",
"maxFieldsetsDescription": "How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.",
"enableMultipleFieldsets": "Enable Multiple Fieldsets?",
"enableMultipleFieldsetsDescription": "Allows multiple types of fieldsets within this archetype.",
"hideFieldsetToolbar": "Hide Fieldset Toolbar?",
"hideFieldsetToolbarDescription": "Hides the fieldset toolbar that appears when more than one fieldset model appears.",
"customWrapperClass": "Custom Wrapper Class",
"customWrapperClassDescription": "(Optional) Enter a custom CSS class that will be applied to the wrapper div.",
"cssFile": "CSS File",
"cssFileDescription": "(Optional) Enter a path for a custom CSS file to be included on the page.",
"jsFile": "JS File",
"jsFileDescription": "(Optional) Enter a path for a custom JS file to be included on the page.",
"toggleDeveloperMode": "Toggle Developer Mode",
"toggleDeveloperModeDescription": "Turn on for developer options.",
"configModel": "Config Model",
"configModelDescription": "Be careful editing the text below, it controls the schema for this archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
"required": "Required",
"regEx": "RegEx Validation",
"properties": "Properties",
"labelTemplate": "Label Template",
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+7 -1
View File
@@ -33,5 +33,11 @@
"select": "Select",
"icon": "Icon",
"enableDisabling": "Enable Fieldset Disabling?",
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled."
"enableDisablingDescription": "Allows fieldsets to be individually enabled/disabled.",
"deepDatatypeRequest":"Enable Deep Datatype Requests?",
"deepDatatypeRequestDescription":"Allows for easier datatype interception at the cost of caching performance.",
"overrideDefaultConverterDescription":"Check this if you wish to use your own custom property value converter.",
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning."
}
+275 -270
View File
@@ -1,113 +1,222 @@
.archetypeEditor {
/* TODO: clean this up */
.archetypeEditor {
width: 98%;
.open {
position: relative;
}
.dropdown-menu {
top: auto;
> li > a {
border-radius: 6px;
}
}
.controls-no-label {
padding: 10px;
}
}
.archetypeEditor fieldset{
border: 1px solid #dddddd;
padding: 0;
margin-bottom: 5px;
background-color: #f1f1f1;
clear: both;
display: inline-block;
width: 100%;
}
a+ul.dropdown-menu {
margin-left: 0;
}
.archetypeEditor .archetypeFieldsetLabel {
position: relative;
width: 100%%;
.icon {
color: #333;
}
.label-sub {
padding: 8px 0;
.fieldsetIcon {
float: left;
padding-right: 4px;
}
fieldset {
border: 1px solid #dddddd;
padding: 0;
margin-bottom: 5px;
background-color: #f1f1f1;
clear: both;
display: inline-block;
&.module-label {
width: 100%;
.archetypeProperty {
clear: both;
overflow: visible;
margin-top: 3px;
label {
padding-left: 5px !important;
span {
color: #343434;
}
&.dimmed span {
color: #d9d9d9;
}
}
}
.archetypeFieldsetLabel {
position: relative;
width: 100%;
min-height: 42px;
.label-sub {
padding: 8px 0 4px 0;
display: inline-block;
&.module-label {
width: 100%;
}
}
.dropdown-menu {
position: relative;
padding: 0;
border-radius: 0;
box-shadow: none;
margin-top: -10px;
}
span {
font-weight: bold;
&.menu-label { font-weight: normal; }
}
label:hover {
cursor: default;
}
&.enableCollapsing:hover {
cursor: pointer;
label {
span {
text-decoration: underline;
}
&:hover {
cursor: pointer;
}
}
}
.caret {
margin: 8px 1px 0 15px;
position: absolute;
&.caret-right {
border-bottom: 4px solid transparent;
border-top: 4px solid transparent;
border-left: 4px solid #000000;
content: "";
margin-top: 6px;
}
}
label {
margin-bottom: 0;
margin-left: 38px;
white-space: nowrap;
padding: 0;
width: ~"calc(100% - 132px)";
position: absolute;
span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
&.dimmed {
color: #d9d9d9;
}
}
.archetypeEditorControls {
float: none;
position: absolute;
right: 15px;
top: 0;
}
}
.archetypePropertyError {
margin-bottom: 5px;
padding-top: 3px;
padding-bottom: 3px;
label {
span {
color: #b94a48;
font-weight: bold;
}
}
}
.archetypeCollapser {
clear: both;
height: 100%;
padding-top: 12px;
background-color: #fff;
border-top: 1px solid silver;
border-radius: 0 0 0 5px;
form {
margin-left:20px;
.control-label {
padding-top: 0 !important;
}
}
.archetypeFieldsetHelpText {
clear:both;
margin-bottom: 3px;
font-size: 12px;
}
}
}
.dropdown-menu {
padding: 0;
border-radius: 0;
box-shadow: none;
margin-top: -10px;
margin-left: -200px;
.archetypeDeveloperModel
{
font-family: monospace;
width: 98%;
min-height: 100px;
margin-bottom: 10px;
border: 1px solid red;
}
span {
font-weight: bold;
&.menu-label { font-weight: normal; }
.archetypeFieldsetError {
border: 1px solid #b94a48;
}
label:hover {
cursor: default;
}
&.enableCollapsing:hover {
.archetypeAddButton:hover {
text-decoration: none;
cursor: pointer;
label {
span {
text-decoration: underline;
}
&:hover {
cursor: pointer;
}
.archetypeAddButtonText {
text-decoration: underline;
}
}
.caret {
margin: 8px 1px 0 15px;
&.caret-right {
border-bottom: 4px solid transparent;
border-top: 4px solid transparent;
border-left: 4px solid #000000;
content: "";
margin-top: 6px;
}
.multiPropertyTextbox {
margin-bottom: 3px;
}
label{
margin-bottom: 0;
margin-left: 5px;
padding: 0;
ul {
list-style: none;
margin-left: 0;
}
.show-validation.ng-invalid .control-group.error .control-label {
span {
display: inline-block;
}
&.dimmed {
color: #d9d9d9;
color: #343434;
}
}
}
.archetypeEditor .archetypeCollapser{
clear: both;
height: 100%;
padding-top: 12px;
background-color: #fff;
border-top: 1px solid silver;
border-radius: 0 0 0 5px;
}
.archetypeEditor .multiPropertyTextbox{
margin-bottom: 3px;
}
.archetypeEditor ul{
list-style: none;
margin-left: 0;
}
.archetypeEditor,
.archetypeConfig {
.archetypeEditor, .archetypeConfig {
.archetypeEditorControls {
float: right;
@@ -123,213 +232,123 @@
}
}
.archetypeEditor .archetypeEditorControls {
float: none;
position: absolute;
right: 15px;
top: 0;
}
.archetypeConfig .archetypeEditorControls {
float: right;
}
.archetypeEditor form {
margin-left:20px;
.control-label {
padding-top: 0 !important;
}
}
.archetypeEditor .archetypeProperty{
clear: both;
overflow: hidden;
margin-top: 3px;
}
.archetypeEditor .archetypeDeveloperModel
{
font-family: monospace;
width: 98%;
min-height: 100px;
margin-bottom: 10px;
border: 1px solid red;
}
.archetypeEditor .archetypeFieldsetToolbar {
margin-bottom: 10px;
overflow: hidden;
li {
float: left;
padding: 2px 4px;
margin-right: 10px;
border: 1px solid #ddd;
cursor: pointer;
}
}
.archetypeEditor .archetypeFieldsetHeaderText{
clear:both;
margin-bottom: 3px;
font-size: 12px;
}
.archetypeEditor .archetypeFieldsetFooterText{
clear:both;
margin-bottom: 3px;
font-size: 12px;
}
.archetypeEditor .archetypeFieldsetHelpText{
clear:both;
margin-bottom: 3px;
font-size: 12px;
}
.archetypeConfig {
margin-bottom: 20px;
}
.archetypeConfig ul{
list-style: none;
}
.archetypeConfig li{
background-color: #fff;
}
.archetypeConfig label{
width: 120px;
}
.archetypeConfig .archetypeFieldsetWrapper{
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
.archetypeConfig .archetypeFieldsetOption{
margin-bottom: 15px;
input[type=text]{
max-width: 300px;
}
}
.archetypeConfig .archetypeDeveloperModel {
font-family: monospace;
width: 88%;
margin: 5px 10px 10px;
height: 130px;
}
.archetypeConfig .archetypePropertiesWrapper {
border: 1px solid #ddd;
padding: 8px;
margin: -40px 10px 10px 140px;
max-width: 475px;
ul {
padding: 0;
margin: 0;
list-style: none;
}
li {
background-color: #fff;
}
label {
width: 120px;
}
.archetypeEditorControls {
float: right;
}
.archetypeFieldsets {
margin-left: 0;
}
.archetypeFieldsetWrapper {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
background-color: #eee;
}
input[type=text] {
max-width: 190px;
width: auto;
}
.archetypeFieldsetTitle {
cursor: pointer;
overflow: hidden;
}
select {
max-width: 160px;
.archetypeFieldsetOption {
margin-bottom: 15px;
input[type=text]{
max-width: 300px;
}
}
li:last-child {
margin-bottom: 0;
.archetypeDeveloperModel {
font-family: monospace;
width: 88%;
margin: 5px 10px 10px;
height: 130px;
}
}
.archetypeConfig .archetypeFieldsets {
margin-left: 0;
}
.archetypeConfig .archetypeFieldsetTitle {
cursor: pointer;
overflow: hidden;
}
.archetypeConfig .archetypeOptions label{
width: 400px;
}
.archetypeConfig .archetypeAdvancedOptions {
margin-top: 15px;
div {
margin-bottom: 10px;
}
label {
.archetypeOptions label{
width: 400px;
}
}
.archetypeConfig .archetypeMaxFieldsets{
border: 1px solid #ddd;
width: 40px;
text-align: right;
}
.archetypePropertiesWrapper {
border: 1px solid #ddd;
padding: 8px;
margin: -40px 10px 10px 140px;
max-width: 475px;
.archetypeConfig .archetypePropertyTitle {
cursor: pointer;
overflow: hidden;
}
.archetypeConfig .archetypePropertyCollapser{
margin-top: 10px;
div {
margin-bottom: 10px;
}
}
.archetypeEditor .archetypeFieldsetError{
border: 1px solid #b94a48;
}
.archetypeEditor .archetypeProperty {
label {
span {
color: #343434;
}
&.dimmed span {
color: #d9d9d9;
ul {
padding: 0;
margin: 0;
}
}
}
.archetypeEditor .archetypePropertyError{
margin-bottom: 5px;
padding-top: 3px;
padding-bottom: 3px;
li {
padding: 10px;
margin-bottom: 10px;
background-color: #eee;
label {
input[type=text] {
max-width: 190px;
width: auto;
}
span {
color: #b94a48;
font-weight: bold;
select {
max-width: 160px;
}
}
li:last-child {
margin-bottom: 0;
}
}
}
.archetypeEditor .archetypeAddButton:hover {
text-decoration: none;
.archetypeAdvancedOptions {
margin-top: 15px;
div {
margin-bottom: 10px;
}
label {
width: 400px;
}
}
.archetypeAddButtonText {
text-decoration: underline;
.archetypeMaxFieldsets, .archetypeMinFieldsets {
border: 1px solid #ddd;
width: 40px;
text-align: right;
}
.archetypePropertyTitle {
cursor: pointer;
overflow: hidden;
}
.archetypePropertyCollapser {
margin-top: 10px;
div {
margin-bottom: 10px;
}
}
.archetypeFieldsetCollapser {
margin-top: 15px;
}
.fieldsetIcon {
margin-right: 10px;
}
}
@@ -337,17 +356,3 @@
visibility: visible !important;
background-color: #d0e7f1 !important;
}
.archetypeConfig .archetypeFieldsetCollapser {
margin-top: 15px;
}
.archetypeConfig .fieldsetIcon {
margin-right: 10px;
}
.archetypeEditor .show-validation.ng-invalid .control-group.error .control-label {
span {
color: #343434;
}
}
@@ -0,0 +1,36 @@
angular.module('umbraco.resources').factory('archetypePropertyEditorResource', function($q, $http, umbRequestHelper){
return {
getAllDataTypes: function() {
// Hack - grab DataTypes from Tree API, as `dataTypeService.getAll()` isn't implemented yet
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAll"), 'Failed to retrieve datatypes from tree service'
);
},
getDataType: function (guid, useDeepDatatypeLookup, contentTypeAlias, propertyTypeAlias, archetypeAlias, nodeId) {
if(useDeepDatatypeLookup) {
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetByGuid?guid=" + guid + "&contentTypeAlias=" + contentTypeAlias + "&propertyTypeAlias=" + propertyTypeAlias + "&archetypeAlias=" + archetypeAlias + "&nodeId=" + nodeId), 'Failed to retrieve datatype'
);
}
else {
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetByGuid?guid=" + guid , { cache: true }), 'Failed to retrieve datatype'
);
}
},
getPropertyEditorMapping: function(alias) {
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAllPropertyEditors", { cache: true }), 'Failed to retrieve datatype mappings'
).then(function (data) {
var result = _.find(data, function(d) {
return d.alias === alias;
});
if (result != null)
return result;
return "";
});
}
}
});
-29
View File
@@ -1,29 +0,0 @@
angular.module('umbraco.resources').factory('archetypePropertyEditorResource', function($q, $http, umbRequestHelper){
return {
getAllDataTypes: function() {
// Hack - grab DataTypes from Tree API, as `dataTypeService.getAll()` isn't implemented yet
return umbRequestHelper.resourcePromise(
$http.get("/umbraco/backoffice/ArchetypeApi/ArchetypeDataType/GetAll"), 'Failed to retrieve datatypes from tree service'
);
},
getDataType: function(guid) {
return umbRequestHelper.resourcePromise(
$http.get("/umbraco/backoffice/ArchetypeApi/ArchetypeDataType/GetByGuid?guid=" + guid), 'Failed to retrieve datatype'
);
},
getPropertyEditorMapping: function(alias) {
return umbRequestHelper.resourcePromise(
$http.get("/umbraco/backoffice/ArchetypeApi/ArchetypeDataType/GetAllPropertyEditors"), 'Failed to retrieve datatype mappings'
).then(function (data) {
var result = _.find(data, function(d) {
return d.alias === alias;
});
if (result != null)
return result;
return "";
});
}
}
});
+149
View File
@@ -0,0 +1,149 @@
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource, notificationsService) {
//private
var isEntityLookupLoading = false;
var entityCache = [];
var isDatatypeLookupLoading = false;
var datatypeCache = [];
var notificationQueue = [];
var notificationCache = [];
var invalidationCache = [];
function findItem(array, item) {
return _.find(array, function(value){
return value == item;
});
}
return {
notifyEditor: function() {
console.log("queue-v");
console.log(notificationQueue);
console.log("sent-v");
console.log(notificationCache);
if(this.shouldBeNotified("minFieldsets") && !this.hasBeenNotified("minFieldsets")) {
notificationsService.error("Error", "Some of your properties do not contain enough fieldsets.");
this.removeNotification("minFieldsets");
notificationCache.push("minFieldsets");
}
},
clearInvalidations: function() {
invalidationCache = [];
},
addInvalidation: function(key) {
if(!this.hasBeenInvalidated(invalidationCache, key)) {
invalidationCache.push(key);
}
},
removeInvalidation: function(key) {
invalidationCache = _.reject(invalidationCache, function(value){
return value == key;
});
},
hasBeenInvalidated: function(key) {
return (typeof findItem(invalidationCache, key) != 'undefined');
},
clearNotifications: function() {
notificationCache = [];
},
addNotification: function(key) {
if(!this.shouldBeNotified(key) && !this.hasBeenNotified(notificationCache, key)) {
notificationQueue.push(key);
}
},
removeNotification: function(key) {
notificationQueue = _.reject(notificationQueue, function(value){
return value == key;
});
},
shouldBeNotified: function(key) {
return (typeof findItem(notificationQueue, key) != 'undefined');
},
hasBeenNotified: function(key) {
return (typeof findItem(notificationCache, key) != 'undefined');
},
getDataTypeFromCache: function(guid) {
return _.find(datatypeCache, function (dt){
return dt.dataTypeGuid == guid;
});
},
addDatatypeToCache: function(datatype, dataTypeGuid) {
var cachedDatatype = this.getDataTypeFromCache(dataTypeGuid);
if(!cachedDatatype) {
datatype.dataTypeGuid = dataTypeGuid;
datatypeCache.push(datatype);
}
},
getDatatypeByGuid: function(guid) {
var cachedDatatype = this.getDataTypeFromCache(guid);
if(cachedDatatype) {
return cachedDatatype;
}
//go get it from server, but this should already be pre-populated from the directive, but I suppose I'll leave this in in case used ad-hoc
if (!isDatatypeLookupLoading) {
isDatatypeLookupLoading = true;
archetypePropertyEditorResource.getDataType(guid).then(function(datatype) {
datatype.dataTypeGuid = guid;
datatypeCache.push(datatype);
isDatatypeLookupLoading = false;
return datatype;
});
}
return null;
},
getEntityById: function(scope, id, type) {
var cachedEntity = _.find(entityCache, function (e){
return e.id == id;
});
if(cachedEntity) {
return cachedEntity;
}
//go get it from server
if (!isEntityLookupLoading) {
isEntityLookupLoading = true;
scope.resources.entityResource.getById(id, type).then(function(entity) {
entityCache.push(entity);
isEntityLookupLoading = false;
return entity;
});
}
return null;
}
}
});
+265
View File
@@ -0,0 +1,265 @@
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService) {
//private
function executeFunctionByName(functionName, context) {
var args = Array.prototype.slice.call(arguments).splice(2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
if(context && context[func]) {
return context[func].apply(this, args);
}
return "";
}
function getNativeLabel(datatype, value, scope) {
switch (datatype.selectedEditor) {
case "Imulus.UrlPicker":
return imulusUrlPicker(value, scope, {});
case "Umbraco.TinyMCEv3":
return coreTinyMce(value, scope, {});
case "Umbraco.MultiNodeTreePicker":
return coreMntp(value, scope, datatype);
case "Umbraco.MediaPicker":
return coreMediaPicker(value, scope, datatype);
case "Umbraco.DropDown":
return coreDropdown(value, scope, datatype);
default:
return "";
}
}
function coreDropdown(value, scope, args) {
if(!value)
return "";
var prevalue = args.preValues[0].value[value];
if(prevalue) {
return prevalue.value;
}
return "";
}
function coreMntp(value, scope, args) {
var ids = value.split(',');
var type = "Document";
switch(args.preValues[0].value.type) {
case 'content':
type = 'Document';
break;
case 'media':
type = 'media';
break;
case 'member':
type = 'member';
break;
default:
break;
}
var entityArray = [];
_.each(ids, function(id){
if(id) {
var entity = archetypeCacheService.getEntityById(scope, id, type);
if(entity) {
entityArray.push(entity.name);
}
}
});
return entityArray.join(', ');
}
function coreMediaPicker(value, scope, args) {
if(value) {
var entity = archetypeCacheService.getEntityById(scope, value, "media");
if(entity) {
return entity.name;
}
}
return "";
}
function imulusUrlPicker(value, scope, args) {
if(!args.propertyName) {
args = {propertyName: "name"}
}
var entity;
switch (value.type) {
case "content":
if(value.typeData.contentId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.contentId, "Document");
}
break;
case "media":
if(value.typeData.mediaId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.mediaId, "Media");
}
break;
case "url":
return value.typeData.url;
default:
break;
}
if(entity) {
return entity[args.propertyName];
}
return "";
}
function coreTinyMce(value, scope, args) {
if(!args.contentLength) {
args = {contentLength: 50}
}
var suffix = "";
var strippedText = $(value).text();
if(strippedText.length > args.contentLength) {
suffix = "…";
}
return strippedText.substring(0, args.contentLength) + suffix;
}
return {
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
//console.log(scope.model.config);
if(!fieldsetConfigModel)
return "";
var fieldset = scope.model.value.fieldsets[fieldsetIndex];
var fieldsetConfig = scope.getConfigFieldsetByAlias(fieldset.alias);
var template = fieldsetConfigModel.labelTemplate;
if (template.length < 1)
return fieldsetConfig.label;
var rgx = /({{(.*?)}})*/g;
var results;
var parsedTemplate = template;
var rawMatches = template.match(rgx);
var matches = [];
_.each(rawMatches, function(match){
if(match) {
matches.push(match);
}
});
_.each(matches, function (match) {
// split the template in case it consists of multiple property aliases and/or functions
var templates = match.replace("{{", '').replace("}}", '').split("|");
var templateLabelValue = "";
for(var i = 0; i < templates.length; i++) {
// stop looking for a template label value if a previous template part already yielded a value
if(templateLabelValue != "") {
break;
}
var template = templates[i];
//test for function
var beginParamsIndexOf = template.indexOf("(");
var endParamsIndexOf = template.indexOf(")");
//if passed a function
if(beginParamsIndexOf != -1 && endParamsIndexOf != -1)
{
var functionName = template.substring(0, beginParamsIndexOf);
var propertyAlias = template.substring(beginParamsIndexOf + 1, endParamsIndexOf).split(',')[0];
var args = {};
var beginArgsIndexOf = template.indexOf(',');
if(beginArgsIndexOf != -1) {
var argsString = template.substring(beginArgsIndexOf + 1, endParamsIndexOf).trim();
var normalizedJsonString = argsString.replace(/(\w+)\s*:/g, '"$1":');
args = JSON.parse(normalizedJsonString);
}
templateLabelValue = executeFunctionByName(functionName, window, scope.getPropertyValueByAlias(fieldset, propertyAlias), scope, args);
}
//normal {{foo}} syntax
else {
propertyAlias = template;
var rawValue = scope.getPropertyValueByAlias(fieldset, propertyAlias);
templateLabelValue = rawValue;
//determine the type of editor
var propertyConfig = _.find(fieldsetConfigModel.properties, function(property){
return property.alias == propertyAlias;
});
if(propertyConfig) {
var datatype = archetypeCacheService.getDatatypeByGuid(propertyConfig.dataTypeGuid);
if(datatype) {
//try to get built-in label
var label = getNativeLabel(datatype, templateLabelValue, scope);
if(label) {
templateLabelValue = label;
}
else {
templateLabelValue = templateLabelValue;
}
}
}
else {
return templateLabelValue;
}
}
}
if(!templateLabelValue) {
templateLabelValue = "";
}
parsedTemplate = parsedTemplate.replace(match, templateLabelValue);
});
return parsedTemplate;
}
}
});
@@ -24,7 +24,7 @@ angular.module('umbraco.services').factory('archetypeLocalizationService', funct
initLocalizedResources:function () {
var deferred = $q.defer();
userService.getCurrentUser().then(function(user){
$http.get("/App_plugins/Archetype/langs/" + user.locale + ".js")
$http.get("../App_plugins/Archetype/langs/" + user.locale + ".js", { cache: true })
.then(function(response){
service.resourceFileLoaded = true;
service.dictionary = response.data;
+114
View File
@@ -0,0 +1,114 @@
angular.module('umbraco.services').factory('archetypeService', function (archetypeCacheService) {
//public
return {
//helper that returns a JS ojbect from 'value' string or the original string
jsonOrString: function (value, developerMode, debugLabel){
if(value && typeof value == 'string'){
try{
if(developerMode == '1'){
console.log("Trying to parse " + debugLabel + ": " + value);
}
value = JSON.parse(value);
}
catch(exception)
{
if(developerMode == '1'){
console.log("Failed to parse " + debugLabel + ".");
}
}
}
if(value && developerMode == '1'){
console.log(debugLabel + " post-parsing: ");
console.log(value);
}
return value;
},
getFieldsetByAlias: function (fieldsets, alias)
{
return _.find(fieldsets, function(fieldset){
return fieldset.alias == alias;
});
},
getPropertyIndexByAlias: function(properties, alias){
for (var i in properties)
{
if (properties[i].alias == alias) {
return i;
}
}
},
getPropertyByAlias: function (fieldset, alias){
return _.find(fieldset.properties, function(property){
return property.alias == alias;
});
},
getUniquePropertyAlias: function (currentScope, propertyAliasParts) {
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
{
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
propertyAliasParts.push(currentPropertyAlias);
}
else if (currentScope.hasOwnProperty('isPreValue')) // Crappy way to identify this is the umbraco property scope
{
var umbracoPropertyAlias = currentScope.$parent.$parent.property.alias; // Crappy way to get the umbraco host alias once we identify its scope
propertyAliasParts.push(umbracoPropertyAlias);
}
if (currentScope.$parent)
this.getUniquePropertyAlias(currentScope.$parent, propertyAliasParts);
return _.unique(propertyAliasParts).reverse().join("-");
},
getFieldset: function(scope) {
return scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex];
},
getFieldsetProperty: function (scope) {
return this.getFieldset(scope).properties[scope.renderModelPropertyIndex];
},
setFieldsetValidity: function (fieldset) {
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
fieldset.isValid =
_.find(fieldset.properties, function (property) {
return property.isValid == false
}) == null;
},
validateProperty: function (fieldset, property, configFieldsetModel) {
var propertyConfig = this.getPropertyByAlias(configFieldsetModel, property.alias);
if (propertyConfig) {
// use property.value !== property.value to check for NaN values on numeric inputs
if (propertyConfig.required && (property.value == null || property.value === "" || property.value !== property.value)) {
property.isValid = false;
}
// issue 116: RegEx validate property value
// Only validate the property value if anything has been entered - RegEx is considered a supplement to "required".
if (property.isValid == true && propertyConfig.regEx && property.value) {
var regEx = new RegExp(propertyConfig.regEx);
if (regEx.test(property.value) == false) {
property.isValid = false;
}
}
}
this.setFieldsetValidity(fieldset);
},
// called when the value of any property in a fieldset changes
propertyValueChanged: function (fieldset, property) {
// it's the Umbraco way to hide the invalid state when altering an invalid property, even if the new value isn't valid either
property.isValid = true;
this.setFieldsetValidity(fieldset);
},
validateMinFieldsets: function(scope) {
//ngModelCtrl.$setValidity('propertyForm', true);
archetypeCacheService.removeInvalidation("minFieldsets");
if(scope.archetypeConfig.minFieldsets && scope.archetypeRenderModel.fieldsets.length < scope.archetypeConfig.minFieldsets) {
//ngModelCtrl.$setValidity('propertyForm', false);
archetypeCacheService.addInvalidation("minFieldsets");
archetypeCacheService.addNotification("minFieldsets");
}
}
}
});
+17 -1
View File
@@ -97,6 +97,10 @@
<label for="archetypeAdvancedOptionsHideLabels"><archetype-localize key="hidePropertyLabels">Hide Property Labels?</archetype-localize><small><archetype-localize key="hidePropertyLabelsDescription">Hides the property labels.</archetype-localize></small></label>
<input type="checkbox" id="archetypeAdvancedOptionsHideLabels" ng-model="archetypeConfigRenderModel.hidePropertyLabels"/>
</div>
<div>
<label for="archetypeAdvancedOptionsMinFieldsets"><archetype-localize key="minFieldsets">Min Fieldsets</archetype-localize><small><archetype-localize key="minFieldsetsDescription">How many Fieldsets are required? Leaving blank will disable the control. Default is unlimited.</archetype-localize></small></label>
<input type="number" id="archetypeAdvancedOptionsMinFieldsets" class="archetypeMinFieldsets" ng-model="archetypeConfigRenderModel.minFieldsets"/>
</div>
<div>
<label for="archetypeAdvancedOptionsMaxFieldsets"><archetype-localize key="maxFieldsets">Max Fieldsets</archetype-localize><small><archetype-localize key="maxFieldsetsDescription">How many Fieldsets are allowed? Entering '1' will disable the controls. Default is unlimited.</archetype-localize></small></label>
<input type="number" id="archetypeAdvancedOptionsMaxFieldsets" class="archetypeMaxFieldsets" ng-model="archetypeConfigRenderModel.maxFieldsets"/>
@@ -108,6 +112,10 @@
<div>
<label for="archetypeAdvancedOptionsCollapsing"><archetype-localize key="enableCollapsing">Enable Collapsing?</archetype-localize><small><archetype-localize key="enableCollapsingDescription">Enable fieldset collapsing.</archetype-localize></small></label>
<input type="checkbox" id="archetypeAdvancedOptionsCollapsing" ng-model="archetypeConfigRenderModel.enableCollapsing"/>
</div>
<div>
<label for="archetypeAdvancedOptionsCloning"><archetype-localize key="enableCloning">Enable Cloning?</archetype-localize><small><archetype-localize key="enableCloningDescription">Enable fieldset cloning.</archetype-localize></small></label>
<input type="checkbox" id="archetypeAdvancedOptionsCloning" ng-model="archetypeConfigRenderModel.enableCloning"/>
</div>
<div>
<label for="archetypeAdvancedOptionsDisabling"><archetype-localize key="enableDisabling">Enable Fieldset Disabling?</archetype-localize><small><archetype-localize key="enableDisablingDescription">Allows fieldsets to be individually enabled/disabled.</archetype-localize></small></label>
@@ -134,9 +142,17 @@
<input type="text" id="archetypeAdvancedOptionsCustomView" ng-model="archetypeConfigRenderModel.customViewPath"/>
</div>
<div>
<label for="archetypeAdvancedOptionsDeveloperMode"><archetype-localize key="toggleDeveloperMode">Toggle Developer Mode</archetype-localize><small><archetype-localize key="toggleDeveloperModeDescription">Toggle Developer Mode</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsDeepDatatypeRequest"><archetype-localize key="deepDatatypeRequest">Enable Deep Datatype Requests?</archetype-localize><small><archetype-localize key="deepDatatypeRequestDescription">Allows for easier datatype interception at the cost of caching performance.</archetype-localize></small></label>
<input type="checkbox" id="archetypeAdvancedOptionsDeepDatatypeRequest" ng-model="archetypeConfigRenderModel.enableDeepDatatypeRequests"/>
</div>
<div>
<label for="archetypeAdvancedOptionsDeveloperMode"><archetype-localize key="toggleDeveloperMode">Enable Developer Mode?</archetype-localize><small><archetype-localize key="toggleDeveloperModeDescription">Toggle Developer Mode</archetype-localize></small></label>
<input type="checkbox" id="archetypeAdvancedOptionsDeveloperMode" ng-model="archetypeConfigRenderModel.developerMode"/>
</div>
<div>
<label for="archetypeOverrideDefaultConverter"><archetype-localize key="overrideDefaultConverter">Override Default Property Value Converter?</archetype-localize><small><archetype-localize key="overrideDefaultConverterDescription">Check this if you wish to use your own custom property value converter.</archetype-localize></small></label>
<input type="checkbox" id="archetypeOverrideDefaultConverter" ng-model="archetypeConfigRenderModel.overrideDefaultPropertyValueConverter" />
</div>
<div>
<label for="archetypeAdvancedOptionsConfigModel"><archetype-localize key="configModel">Config Model</archetype-localize><small><archetype-localize key="configModelDescription">Be careful editing the text below, it controls the schema for this archetype.</archetype-localize></small></label>
<textarea class="archetypeDeveloperModel" id="archetypeAdvancedOptionsConfigModel" ng-model="archetypeConfigRenderModel"></textarea>
+9 -7
View File
@@ -2,7 +2,7 @@
<textarea class="archetypeDeveloperModel" ng-show="model.config.developerMode" ng-model="model.value"></textarea>
<ul ui-sortable="sortableOptions" ng-model="model.value.fieldsets" ng-show="!showAddButton()">
<li ng-repeat="fieldset in model.value.fieldsets">
<fieldset ng-class="[fieldset.alias, (getFieldsetValidity(fieldset) == false ? 'archetypeFieldsetError' : '')]" ng-init="fieldsetConfigModel = getConfigFieldsetByAlias(fieldset.alias)">
<fieldset ng-class="['archetype-fieldset-' + fieldset.alias, (getFieldsetValidity(fieldset) == false ? 'archetypeFieldsetError' : '')]" ng-init="fieldsetConfigModel = getConfigFieldsetByAlias(fieldset.alias)">
<div class="archetypeFieldsetLabel" ng-class="{enableCollapsing: model.config.enableCollapsing}">
<div ng-click="focusFieldset(fieldset)" class="label-sub module-label">
<span class="caret" ng-hide="fieldset.collapse || !model.config.enableCollapsing"></span>
@@ -22,23 +22,25 @@
</a>
</li>
</ul>
<i class="icon icon-documents" ng-click="cloneRow($index)" ng-show="canClone()"></i>
<i class="icon icon-remove" ng-click="removeRow($index)" ng-show="canRemove()"></i>
<i class="icon icon-power" ng-class="{dimmed: fieldset.disabled}" ng-click="enableDisable(fieldset)" ng-show="canDisable()"></i>
<i class="icon icon-navigation handle" ng-show="canSort()"></i>
</div>
</div>
<div class="archetypeCollapser animate-hide" ng-hide="isCollapsed(fieldset)">
<div class="archetypeCollapser animate-hide" ng-hide="model.config.enableCollapsing && isCollapsed(fieldset)">
<form class="form-inline">
<div ng-class="[property.alias, (getPropertyValidity($parent.$index, property.alias) === false ? 'archetypePropertyError' : '')]" class="archetypeProperty control-group" ng-repeat="property in fieldsetConfigModel.properties">
<label ng-hide="archetypeConfig.hidePropertyLabels == '1'" class="control-label" for="archetype-property-{{umbracoHostPropertyAlias}}-f{{$parent.$index}}-{{property.alias}}-p{{$index}}">
<div ng-class="[('archetype-property-' + property.alias), (getPropertyValidity($parent.$index, property.alias) === false ? 'archetypePropertyError' : '')]" class="archetypeProperty control-group" ng-repeat="property in fieldsetConfigModel.properties">
<label ng-hide="model.config.hidePropertyLabels == '1'" class="control-label" for="archetype-property-{{model.alias}}-{{$parent.$index}}-{{$index}}">
<span>{{property.label}}</span>
<div class="archetypeFieldsetHelpText" ng-show="property.helpText">
<small>{{property.helpText}}</small>
</div>
</label>
<div class="controls">
<archetype-property class="archetypeEditor" property="property" fieldset-index="$parent.$index" fieldset="fieldset" archetype-config="model.config" property-config-index="$index" archetype-render-model="model.value" umbraco-form = "form"></archetype-property>
<div ng-class="[(model.config.hidePropertyLabels == '1' ? 'controls-no-label' : 'controls')]">
<archetype-property class="archetypeEditor" property="property" property-editor-alias="model.alias" fieldset-index="$parent.$index" fieldset="fieldset" archetype-config="model.config" property-config-index="$index" archetype-render-model="model.value" umbraco-form="form"></archetype-property>
<archetype-submit-watcher active-submit-watcher="activeSubmitWatcher" load-callback="submitWatcherOnLoad" submit-callback="submitWatcherOnSubmit"></archetype-submit-watcher>
</div>
</div>
</form>
@@ -47,7 +49,7 @@
</li>
</ul>
<div ng-show="showAddButton()">
<a data-toggle="{{ model.config.fieldsets.length > 1 ? 'dropdown' : ''}}" ng-click="model.config.fieldsets.length == 1 ? addRow(model.config.fieldsets[0].alias, 0) : return" prevent-default>
<a class="archetypeAddButton" data-toggle="{{ model.config.fieldsets.length > 1 ? 'dropdown' : ''}}" ng-click="model.config.fieldsets.length == 1 ? addRow(model.config.fieldsets[0].alias, 0) : return" prevent-default>
<i class="icon icon-add dropdown-toggle"></i>
<localize key="general_add" class="archetypeAddButtonText">Add</localize>
</a>
+2 -2
View File
@@ -1,8 +1,8 @@
{
"name": "Archetype",
"version": "1.3.0-beta",
"version": "1.9",
"url": "http://github.com/imulus/archetype/",
"author": "Imulus",
"author": "Imulus - Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Et. Al.",
"authorUrl": "http://imulus.com/",
"license": "MIT",
"licenseUrl": "http://opensource.org/licenses/MIT"
+15 -12
View File
@@ -1,15 +1,18 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Archetype</id>
<version><%= version %></version>
<title><%= name %></title>
<authors>imulus, kgiszewski, tomfulton</authors>
<owners>imulus, kgiszewski, tomfulton</owners>
<projectUrl>http://github.com/imulus/archetype</projectUrl>
<description><![CDATA[Archetype for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
</metadata>
<metadata>
<id>Archetype</id>
<version><%= version %></version>
<title><%= name %></title>
<authors>imulus, kgiszewski, tomfulton</authors>
<owners>imulus, kgiszewski, tomfulton</owners>
<projectUrl>http://github.com/imulus/archetype</projectUrl>
<description><![CDATA[Archetype for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
<dependencies>
<dependency id="UmbracoCms.Core" version="7.1.6" />
</dependencies>
</metadata>
</package>
+1 -1
View File
@@ -22,7 +22,7 @@
"grunt-msbuild": "~0.1.9",
"grunt-dotnet-assembly-info": "~1.0.9",
"load-grunt-tasks": "~0.4.0",
"grunt-umbraco-package": "0.0.5"
"grunt-umbraco-package": "0.0.6"
},
"repository": {
"type": "git",