Compare commits

...

278 Commits

Author SHA1 Message Date
Kevin Giszewski a4c1a59e23 Merge pull request #436 from kgiszewski/feature/slow-the-updates-roll
Feature/slow the updates roll
2017-10-07 07:10:36 -04:00
Kevin Giszewski e164be1823 Merge logic 2017-10-03 13:31:43 -04:00
Kevin Giszewski f32451fffa Clean up private var 2017-10-03 13:28:25 -04:00
Kevin Giszewski a541dbd038 Limit the version check to once every 7 days (unless the app is reloaded) 2017-10-03 13:27:03 -04:00
Kevin Giszewski 69e0bb70e5 Fix scrunchy fieldset picker titles 2017-10-03 11:07:10 -04:00
Kevin Giszewski c22a2623c2 Merge pull request #434 from ceee/ui-refactor
Update UI to better match Grid & Nested Content
2017-10-03 08:56:52 -04:00
swcs c229cc9953 correct layout for cross dragging between archetype instances 2017-10-03 14:32:34 +02:00
swcs 7d155ee176 force visibility of editor controls if a fieldset collapser is open 2017-10-02 15:49:37 +02:00
swcs 93659e5a22 increase char limit for RTE label generator from 50 to 160 2017-10-02 15:40:04 +02:00
swcs 46bbf24edf limit fieldset label to 2 lines 2017-09-29 10:34:34 +02:00
swcs da1057c681 fix style for nested archetype fieldsets 2017-09-28 14:14:16 +02:00
swcs 81881a5734 allow 100% width for fieldset labels and add background for controls on the right 2017-09-28 14:05:09 +02:00
swcs 25678a812c new empty content display and add button 2017-09-26 11:25:51 +02:00
Kevin Giszewski ec2edce74c Bump version 2017-09-25 13:31:52 -04:00
Kevin Giszewski 4756551518 Merge pull request #433 from Nicholas-Westby/fix/432-resolve-label-templates
Fix for label templates sometimes not resolving: https://github.com/k…
2017-09-25 08:28:23 -04:00
Nicholas-Westby e053b42950 Fix for label templates sometimes not resolving: https://github.com/kgiszewski/Archetype/issues/432 2017-09-23 17:16:50 -07:00
swcs ff21951ea1 make the container/boundaries for the fieldset collapser more visible 2017-09-21 14:22:21 +02:00
swcs 18935b4a69 update control icons and do only show them on fieldset hover 2017-09-21 13:41:47 +02:00
swcs cd93e17494 improve fieldset list layout and spacing 2017-09-21 13:15:58 +02:00
Kevin Giszewski 3a2190b232 Merge pull request #431 from kgiszewski/feature/letstryagain
Feature/letstryagain
2017-09-20 08:03:00 -04:00
Kevin Giszewski 46b0396652 Use a quicker cache lookup 2017-09-19 08:52:51 -04:00
Kevin Giszewski 0c3fcce58b Add args example 2017-09-15 15:50:39 -04:00
Kevin Giszewski cef7a36bd4 I remember adding these and now I think that was dumb. We should be injecting these :) 2017-09-15 13:41:24 -04:00
Kevin Giszewski 03d511ca80 Update sampleLabelHelpers and inject entityResource instead of off the scope 2017-09-15 13:39:18 -04:00
Kevin Giszewski 123546b11c Promise fixes 2017-09-15 12:46:33 -04:00
Kevin Giszewski 4aa6b83d82 Move to all promises, this is WIP 2017-09-15 10:58:04 -04:00
Kevin Giszewski 6f3a414c4d Handle native stuff a bit differently 2017-09-13 22:19:09 -04:00
Kevin Giszewski 4443d628dc Maybe works? 2017-09-13 21:56:43 -04:00
Kevin Giszewski 0f9a44c539 RTE is working, but not the UrlPicker one 2017-09-13 18:18:29 -04:00
Kevin Giszewski dd47218bd3 Add an asset only task 2017-09-13 17:15:11 -04:00
Kevin Giszewski 5e3e37af31 Update package.nuspec 2017-09-12 10:57:13 -04:00
Kevin Giszewski dbf1bffe34 Update package_binaries.nuspec 2017-09-12 10:56:53 -04:00
Kevin Giszewski cbf87264ac Update package_courier.nuspec 2017-09-12 10:56:41 -04:00
Kevin Giszewski 353c3da22a Update Information Collection Disclosure.md 2017-09-12 10:27:07 -04:00
Kevin Giszewski 9d15e0c696 Update README.md 2017-09-12 10:26:10 -04:00
Kevin Giszewski 7dc7b8f938 Update README.md 2017-09-12 10:25:26 -04:00
Kevin Giszewski f8302b0926 Update README.md 2017-09-12 10:22:12 -04:00
Kevin Giszewski 1cb3f4e266 Merge branch 'master' of https://github.com/kgiszewski/Archetype 2017-09-12 10:16:40 -04:00
Kevin Giszewski d2b7a9a92b Delete tonic_logo_50.png 2017-09-12 10:16:24 -04:00
Kevin Giszewski 245f4ed972 Update TOS -> Disclosure 2017-09-12 10:15:06 -04:00
Kevin Giszewski 19ef383a71 Update Information Collection Disclosure.md 2017-09-12 10:12:57 -04:00
Kevin Giszewski af2287d2fc Add files via upload 2017-09-12 10:12:43 -04:00
Kevin Giszewski e4c206211f Delete optout2.png 2017-09-12 10:12:34 -04:00
Kevin Giszewski 57a199d235 Update Information Collection Disclosure.md 2017-09-12 10:11:45 -04:00
Kevin Giszewski 2a98005ae7 Add files via upload 2017-09-12 10:11:27 -04:00
Kevin Giszewski 69a7256538 Delete optout.png 2017-09-12 10:10:53 -04:00
Kevin Giszewski 38dc405183 Rename Information Collection Disclosure to Information Collection Disclosure.md 2017-09-12 10:06:17 -04:00
Kevin Giszewski d6874e7cd8 Update Information Collection Disclosure 2017-09-12 10:02:09 -04:00
Kevin Giszewski c1e732e3de Update and rename Terms of Service.md to Information Collection Disclosure 2017-09-12 10:01:42 -04:00
Kevin Giszewski 02ffe4db4a Update Terms of Service.md 2017-09-12 09:50:46 -04:00
Kevin Giszewski c79be2f6db Update Terms of Service.md 2017-09-12 09:49:33 -04:00
Kevin Giszewski f0c15ade5d Update Terms of Service.md 2017-09-12 09:48:02 -04:00
Kevin Giszewski 9f8acedf6f Add files via upload 2017-09-12 09:46:18 -04:00
Kevin Giszewski aba3bdd2c4 Update Terms of Service.md 2017-09-12 09:44:59 -04:00
Kevin Giszewski de491f9687 Update Terms of Service.md 2017-09-12 09:43:57 -04:00
Kevin Giszewski 2becf8a1ba Merge pull request #426 from kgiszewski/feature/version-check
Feature/version check
2017-09-12 09:31:03 -04:00
Kevin Giszewski 68a5a9893d Update Sponsors.md 2017-09-08 09:15:11 -04:00
Kevin Giszewski 3ed08c447c Update Sponsors.md 2017-09-08 09:14:44 -04:00
Kevin Giszewski 9a2e14d8f6 Add sponsors 2017-09-08 09:09:38 -04:00
Kevin Giszewski d557ec1edb Update README.md 2017-09-08 09:07:30 -04:00
Kevin Giszewski 4fb7cdc5e5 Create Sponsors.md 2017-09-08 09:06:29 -04:00
Kevin Giszewski 5fa225b460 Update README.md 2017-09-08 09:05:34 -04:00
Kevin Giszewski b1f8c6a732 Merge pull request #425 from Nicholas-Westby/feature/422-label-template-enhancements
Feature/422 label template enhancements
2017-09-07 14:26:48 -04:00
Kevin Giszewski 7d8a6e28fa Test Sponsors 2017-09-07 14:15:28 -04:00
Kevin Giszewski 6a9c56df58 Add locking to the file saving. Update casing on English lang files. 2017-09-07 13:13:37 -04:00
Nicholas-Westby fa265d3019 Avoid exception when there is no label template. 2017-09-07 08:30:09 -07:00
Kevin Giszewski 078f4a506e Add obfuscation 2017-09-07 11:01:29 -04:00
Kevin Giszewski 42661c27f4 Update archetype.config.html 2017-09-07 09:21:48 -04:00
Kevin Giszewski b398e0e677 Merge pull request #427 from GertyEngrie/feature/required-property-indication
Indicate in the datatype configuration if a property is required or not
2017-09-07 09:17:36 -04:00
Kevin Giszewski a54170b915 Naming is hard. 2017-09-07 09:08:47 -04:00
Kevin Giszewski 757ba890f5 Update links and blurb in the config 2017-09-07 09:03:39 -04:00
Kevin Giszewski a127dac03a Move off the web.config in favor of an Archetype config 2017-09-07 08:55:26 -04:00
Gerty Engrie 62e481d49c Indicate in the datatype configuration if a property is required or not 2017-09-07 11:30:21 +02:00
Kevin Giszewski 77ec2d7a9c Update meta.json 2017-09-06 21:22:00 -04:00
Kevin Giszewski 0d55f0ed86 Add a URL to the notification 2017-09-06 21:00:32 -04:00
Kevin Giszewski 6a7ac205bc Update the url to call and use JSON Convert 2017-09-06 19:53:25 -04:00
Kevin Giszewski 1cb2139137 More WIP 2017-09-06 18:32:48 -04:00
Kevin Giszewski b14645f13f Update Terms of Service.md 2017-09-06 17:25:05 -04:00
Kevin Giszewski b8741726bc Update README.md 2017-09-06 17:21:35 -04:00
Kevin Giszewski d392c4f705 Update Terms of Service.md 2017-09-06 17:20:16 -04:00
Kevin Giszewski 119b0c7680 Create Terms of Service.md 2017-09-06 17:19:43 -04:00
Kevin Giszewski b9179f4140 WIP on version checking 2017-09-06 12:20:52 -04:00
Nicholas-Westby d46d64c52b Allow for other data types to be used with label template functions. 2017-09-06 08:18:43 -07:00
Nicholas-Westby 45318cf061 Merge remote-tracking branch 'upstream/master' into feature/422-label-template-enhancements 2017-09-05 21:01:55 -07:00
Nicholas-Westby b9abf0d6a3 Allow for services to be injected into label template functions.
Allow the value returned from a label template function to be recursively resolved until it finally becomes a string.
2017-09-05 20:51:45 -07:00
Nicholas-Westby e00229984c Label templates can now return a promise that eventually resolves to a string. 2017-09-05 19:39:33 -07:00
Nicholas-Westby 155f212062 New approach to splitting the label template (will make the upcoming promises work easier). In short, each substring is stored into an array, those items are modified, then when all the modifications are done the substrings are combined again. 2017-09-04 20:26:16 -07:00
Nicholas-Westby 86a8112fbd Fixed regex so it doesn't match empty strings.
Removed unused variable.
2017-09-04 19:15:49 -07:00
Nicholas-Westby 810fa95c65 Removed some extraneous and probably buggy code related to label templates. 2017-09-04 19:06:12 -07:00
Nicholas-Westby 9bcd9d67ae Update the Archetype controller to allow for fieldset titles to be loaded using promises (still need to actually allow for promises). 2017-09-04 15:49:30 -07:00
Kevin Giszewski bae1ee508b Update README.md 2017-09-04 17:26:56 -04:00
Kevin Giszewski 20b6a78af1 Update some stuffs for nuget 2017-08-18 09:20:45 -04:00
Kevin Giszewski 014b407abb Let's do purple 2017-08-18 09:03:03 -04:00
Kenn Jacobsen 5aa16a6636 Bump package version 2017-08-18 08:10:43 +02:00
Kenn Jacobsen 7206bba46a Merge pull request #423 from kjac/min-fieldsets-feature
Add minimum fieldsets feature
2017-08-15 12:43:07 +02:00
Kenn Jacobsen af9db94fb6 Merge pull request #421 from kjac/Fix-418
Fix #418
2017-08-09 13:37:50 +02:00
Kenn Jacobsen d2014be81b Fix #418
Don't let the entire published content conversion break if one property
no longer exists.
2017-08-09 13:36:59 +02:00
Kenn Jacobsen 01b8b3b508 Merge remote-tracking branch 'refs/remotes/origin/master' into min-fieldsets-feature 2017-08-09 13:24:35 +02:00
Kenn Jacobsen 734125fa25 Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-08-09 13:24:06 +02:00
Kenn Jacobsen 76678f538d Merge pull request #420 from kjac/fix-414
Fix #414
2017-08-09 13:22:55 +02:00
Kenn Jacobsen 7fe23fdf4c Fix #414
Using ng-src instead of src fixes the issue.
2017-08-09 13:22:05 +02:00
Kenn Jacobsen c956c12cdf Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-08-09 13:16:19 +02:00
Kenn Jacobsen 8706feb882 Merge pull request #419 from kjac/fix-417
Tested with a custom property editor to make sure the JSON default value works.
2017-08-09 12:58:59 +02:00
Kenn Jacobsen c8364986a2 Fix #417
Don't turn an object into a string if it's not...
2017-08-09 12:49:47 +02:00
Kenn Jacobsen 4d24150bdc Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-08-09 12:48:17 +02:00
kjac a16c4b4da9 Merge remote-tracking branch 'refs/remotes/kgiszewski/master' into min-fieldsets-feature 2017-07-28 16:09:49 +02:00
Kevin Giszewski 75a312c309 Update README.md 2017-06-26 09:12:11 -04:00
Kenn Jacobsen aa6505d7f6 Merge pull request #412 from kjac/master
Bump package version
2017-06-13 08:41:09 +02:00
Kenn Jacobsen 6ed7af28bc Bump package version 2017-06-13 08:38:31 +02:00
Kenn Jacobsen 526f4c147a Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-13 08:28:22 +02:00
Kenn Jacobsen bb0df72dc7 Merge pull request #411 from kjac/fieldset-preview-image
Add fieldset image previews
2017-06-13 08:27:39 +02:00
Kenn Jacobsen 3cba5677bf Whoops... the preview image shouldn't be mandatory 2017-06-13 08:25:05 +02:00
kjac c4f88ab528 Remove max width comment 2017-06-12 22:29:16 +02:00
kjac 7bc9584940 Add min fieldsets handling 2017-06-12 22:26:03 +02:00
kjac 17be4b4253 Merge remote-tracking branch 'refs/remotes/origin/master' into fieldset-preview-image 2017-06-12 22:11:07 +02:00
kjac 2db196af6a Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-12 22:09:29 +02:00
Kenn Jacobsen b4b27cd1f8 Merge pull request #410 from kjac/mandatory-validation-disabled-fieldsets
Handle disabled fieldsets in mandatory validation
2017-06-12 22:07:02 +02:00
kjac a2cc052944 Handle disabled fieldsets in mandatory validation
Disabled fieldsets should not count when performing mandatory
validation. This ensures they aren't.
2017-06-12 22:04:46 +02:00
kjac 4d8a4f0b12 Merge remote-tracking branch 'refs/remotes/origin/master' into fieldset-preview-image 2017-06-11 22:10:07 +02:00
kjac 743f37c45f Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-11 22:09:40 +02:00
Kenn Jacobsen 1ba45969ee Merge pull request #409 from kjac/multiple-open-fieldsets
Enable multiple open fieldsets by datatype configuration. It's default enabled on newly created Archetypes.
2017-06-11 22:08:48 +02:00
kjac 349d6f69b3 Enable multiple open fieldsets
See #196
2017-06-11 22:06:14 +02:00
kjac 9431a70156 Merge remote-tracking branch 'refs/remotes/origin/master' into fieldset-preview-image 2017-06-11 21:38:04 +02:00
kjac ab780f72a4 Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-11 21:37:39 +02:00
Kenn Jacobsen 7d01be305f Merge pull request #408 from kjac/fix-mandatory-validation
Fix mandatory validation: The mandatory validation implementation prevents a valid Archetype from
being submitted on the first go because the mandatory validation isn't
initialized.
2017-06-11 21:36:34 +02:00
kjac 694b932e37 Fix mandatory validation issue
The mandatory validation implementation prevents a valid Archetype from
being submitted on the first go because the mandatory validation isn't
initialized.
2017-06-11 21:35:31 +02:00
kjac a4f6334761 Merge branch 'master' into fieldset-preview-image 2017-06-11 16:18:52 +02:00
kjac 9316e7c3f6 Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-11 16:17:46 +02:00
Kenn Jacobsen 8bc6c17921 Merge pull request #407 from kjac/styling-for-7.6
Styling for 7.6: Make the "add new item" button look ok in 7.6 + hide the "drag into"
area for non cross draggable Archetypes.
2017-06-11 16:16:53 +02:00
kjac 1161c7e6da A bit of styling
Make the "add new item" button look ok in 7.6 + hide the "drag into"
area for non cross draggable Archetypes.
2017-06-11 16:14:58 +02:00
kjac 93db3eb2ee Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-11 16:07:24 +02:00
Kenn Jacobsen b7b166562f Merge pull request #406 from kjac/collapsing-dollar-signs
Collapsing dollar signs
2017-06-11 16:05:26 +02:00
kjac e3c4c91de1 Fix #387 2017-06-11 16:03:56 +02:00
kjac f79849cf8a Open preview image in a new window when clicked 2017-06-10 08:49:59 +02:00
kjac f0b27e1507 Merge remote-tracking branch 'refs/remotes/origin/master' into fieldset-preview-image 2017-06-10 08:26:28 +02:00
kjac 42e92a4e74 Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-10 08:26:06 +02:00
Kenn Jacobsen 2c363a5d37 Merge pull request #405 from kjac/mandatory-validation
Mandatory validation - fixes #395
2017-06-09 21:19:32 +02:00
kjac 738e9282b6 Handle mandatory validation
Don't allow submission of an empty Archetype if the property is set to
mandatory
2017-06-09 21:11:11 +02:00
kjac 20fa1efc8e A bit more styling + localization 2017-06-09 21:04:44 +02:00
kjac 718f2deb47 Add preview image to fieldsets
See #374
2017-06-09 20:19:17 +02:00
kjac 1cea5d156a Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-08 16:46:00 +02:00
Kenn Jacobsen 109d4c7708 Merge pull request #404 from kjac/label-templates-for-v2-pickers
Label templates for the V2 pickers
2017-06-08 16:37:50 +02:00
Kenn Jacobsen 8306be60de Merge pull request #403 from kjac/lazy-load-configuration
Lazy load configuration
2017-06-08 16:36:52 +02:00
Kenn Jacobsen 27d0cb742b Label templates for the V2 pickers
..and also for the old content picker (it was missing for whatever
reason) - fixes #402
2017-06-08 09:02:31 +02:00
kjac 62a250cd83 Lazy load fieldsets in configuration
Fixes #393
2017-06-07 23:07:40 +02:00
kjac 6f94d608db Merge remote-tracking branch 'refs/remotes/kgiszewski/master' 2017-06-07 20:56:35 +02:00
Kenn Jacobsen 854e9873c8 Merge pull request #401 from kjac/image-cropper-and-upload-76
Adjust to 7.6 scheme for upload and image croppers
2017-06-07 17:56:20 +02:00
Kenn Jacobsen 2a6d5eaddf Merge pull request #400 from kjac/fix-upload-and-image-cropper-again
Fix upload and image cropper (again)
2017-06-07 17:48:23 +02:00
kjac 3d7ddb58c2 Adjust to 7.6 scheme for upload and image croppers
Fixes #397, at least for newly created sites.
2017-06-06 23:14:40 +02:00
kjac 4c7496840d Fix upload and image cropper (again)
Fixes #384, #389 and #394
2017-06-06 22:41:04 +02:00
Kevin Giszewski d816103981 Merge pull request #399 from codedemonuk/patch-1
Subheadings were not being rendered correctly in Readme
2017-05-29 11:14:18 -04:00
Pervez Choudhury b38ccc12f6 Subheadings were not being rendered correctly 2017-05-28 17:48:44 +01:00
Kevin Giszewski e1deba5b95 Update LICENSE 2017-02-16 12:53:33 -05:00
Kevin Giszewski 5bce4e856a Merge pull request #386 from kgiszewski/fix-385
Fix #385
2017-02-16 12:42:55 -05:00
Kevin Giszewski 6f4cb1e609 Merge pull request #379 from leekelleher/feature/typeconverter
TypeConverter for ArchetypeModel
2017-02-16 12:42:44 -05:00
Kenn Jacobsen 033cbbc8f6 Fix #385 2017-02-16 15:05:21 +01:00
Kenn Jacobsen 7ee3cfca5c Merge pull request #378 from Nicholas-Westby/fix/372-drag-drop-broken
Fix for drag & drop failing when dropping fieldset in the same Archet…
2017-02-16 12:16:44 +01:00
Kenn Jacobsen e9b478c186 Fix #384
For some reason Umbraco has started lowercasing the names of uploaded
files. This fixes the problem by ignoring case when looking for the
uploaded files.
2017-02-15 11:17:01 +01:00
leekelleher 21e784424f TypeConverter for ArchetypeModel
Added a TypeConverter for both `ArchetypeModel` and `ArchetypeFieldsetModel`, so that they can be converted to their `IPublishedContent` equivalent.

Example usage would be, when you would typically do this...

```csharp
var items = Model.Content.GetPropertyValue<ArchetypeModel>myArchetypeAlias");
```

You can now do this...

```csharp
var items = Model.Content.GetPropertyValue<IEnumerable<IPublishedContent>>("myArchetypeAlias");
```

I know it seems more verbose, but the idea is that this could be hot-swappable with other property-editors, such as Nested Content. The frontend/code would deal purely with `IPublishedContent` objects.

---

Also included unit-tests that run via Umbraco Core's `TryConvertTo` extension method, (which is what `Content.GetPropertyValue<T>` uses internally in Umbraco).

There's a small caveat with the TypeConverter for `ArchetypeFieldsetModel`, I had to explicitly reject `typeof(string)`, otherwise the JSON deserializer fails (in `ArchetypeHelper.DeserializeJsonToArchetype`).
All other unit-tests still pass.
2016-10-19 20:26:46 +01:00
Nicholas-Westby 155355aa00 Fix for drag & drop failing when dropping fieldset in the same Archetype and the max fieldsets is reached: https://github.com/kgiszewski/Archetype/issues/372 2016-09-14 22:08:04 -07:00
kgiszewski abf6917b1c bump to v1.13.1 2016-06-26 12:10:11 -04:00
kgiszewski 40ad701f7f Merge branch 'master' into pr/365 2016-06-26 12:05:18 -04:00
Kevin Giszewski a8113f926c Merge pull request #369 from kipusoep/master
Fixed #368
2016-06-16 16:21:21 -04:00
Kevin Giszewski 3c527396de Merge pull request #364 from Nicholas-Westby/fix/362-drag-fieldset-undefined
Fix for error during Archetype drags when there are rich text editors…
2016-06-16 16:12:33 -04:00
Stefan Kip 59bf66dcd1 Fixed #368 2016-06-16 20:11:02 +02:00
Nicholas-Westby c125042a86 Avoid fieldsets that can't be expanded: https://github.com/imulus/Archetype/issues/363 2016-05-20 21:38:39 -07:00
Nicholas-Westby 85ea472129 Fix for error during Archetype drags when there are rich text editors outside of Archetype: https://github.com/imulus/Archetype/issues/362 2016-05-18 20:03:05 -07:00
kgiszewski f541b50b82 Merge branch 'master' into pr/356
Conflicts:
	app/Umbraco/Umbraco.Archetype/Models/ArchetypePreValue.cs
	app/controllers/config.controller.js
	app/views/archetype.config.fieldset.dialog.html
2016-05-13 10:07:18 -04:00
Nicholas-Westby 5767ea97d1 Workaround for .sortable("instance") not working on older versions of Umbraco. 2016-05-11 21:19:09 -07:00
Nicholas-Westby e1fa7a3271 Fixed recursion error and tidied up validation logic. 2016-05-07 15:48:39 -07:00
Nicholas-Westby c2e97e28ce Disable sortables for Archetypes that can't have the currently dragged fieldset dropped onto them. 2016-05-07 14:54:30 -07:00
Nicholas-Westby eda9bab02f Ensure the property alias is unique when dragging between Archetypes. 2016-05-07 12:45:34 -07:00
Nicholas-Westby ce3cecbec9 Fix for incorrect validation errors. 2016-05-05 21:52:03 -07:00
Nicholas-Westby ef5faae254 Allow the last fieldset to be dropped back to its origin list. 2016-05-05 21:18:08 -07:00
Nicholas-Westby 547473e92c Account for the possibility that the "tinyMCE" variable may not exist. 2016-05-05 20:20:44 -07:00
Nicholas-Westby 9857059906 Ensured the temporary ID is unique when cloning fieldsets. 2016-05-05 20:05:20 -07:00
Nicholas-Westby 7f7b054c14 Clear errors on the target Archetype too. 2016-05-04 21:28:16 -07:00
Nicholas-Westby a40d95250e Clear out errors of nested Archetypes on drop. 2016-05-04 21:15:36 -07:00
Nicholas-Westby 1e6004d3fa Another RTE fix.
Improved handling of validations when moving fieldsets (recursively mark Archetypes as valid).
2016-05-04 20:58:26 -07:00
Nicholas-Westby 0671403732 Fix for rich text editors when dragging between Archetypes. 2016-05-03 21:59:04 -07:00
kjac 8e00914370 More code style fixes 2016-05-03 20:17:45 +02:00
kjac 104c369bcc Fix some code style issues 2016-05-03 20:15:23 +02:00
kjac 4c02cf2921 Merge remote-tracking branch 'refs/remotes/origin/master' into allowed-member-groups 2016-05-03 19:44:59 +02:00
kjac 74470b8e8f Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-05-03 19:44:23 +02:00
Nicholas-Westby de92147ec0 WIP: Attempting to fix RTE when dragging between fieldsets (still needs some work). 2016-05-01 21:23:02 -07:00
Nicholas-Westby c2b7d2c89d Allowed rich text editors to be dragged between Archetypes. 2016-05-01 18:27:01 -07:00
Nicholas-Westby d0fe30f08b WIP: Better handling of validation errors when dragging fieldsets between Archetypes.
Added "jsonSnapshot" (utility function for troubleshooting).
Added "tolerance" (my hope is that will help drag operations act nicer with expanded fieldsets).
2016-05-01 17:33:32 -07:00
Nicholas-Westby d22ae1244e Merge remote-tracking branch 'origin/master' into feature/355-nested-dragging 2016-04-30 18:18:14 -07:00
Nicholas-Westby fa48d73630 Only allow cross-Archetype sorting of a single fieldset if it can be removed. 2016-04-28 20:32:07 -07:00
kgiszewski fb305c9d0e Fix label padding in the config 2016-04-28 11:35:05 -04:00
Nicholas-Westby be332d310f Add a top margin of 5px to empty Archetype drop zone. 2016-04-28 08:24:06 -07:00
kjac d97bbb59dc Merge remote-tracking branch 'refs/remotes/origin/master' into allowed-member-groups 2016-04-27 21:00:11 +02:00
kjac 3702ec484b Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-04-27 20:59:42 +02:00
Nicholas-Westby d8d4ec1a73 Improved terminology (fieldsets are dragged across Archetypes, not across fieldsets). 2016-04-27 08:21:16 -07:00
Nicholas-Westby 32cb89bba1 Made cross-field dragging opt-in. 2016-04-26 21:40:19 -07:00
Nicholas-Westby 863f041fc9 Fixed issue when dragging newly created fieldset between Archetypes.
Ensured that fieldset aliases are compared when judging compatibility during drag.
2016-04-26 21:14:33 -07:00
Nicholas-Westby 5a83719dfc Performance optimization via short-circuiting. 2016-04-26 05:57:08 -07:00
Nicholas-Westby 1b1940fe6a Tamed a rogue comment. 2016-04-26 05:54:56 -07:00
kgiszewski b71564bfb5 Merge branch 'pr/351' 2016-04-26 07:51:50 -04:00
kgiszewski ba8a6cf65c Merge branch 'master' into pr/351 2016-04-26 07:37:33 -04:00
Nicholas-Westby 7dd07b9f9c When dragging between Archetypes, only allow the operation when a configured fieldset matches the dragged fieldset. 2016-04-25 21:05:36 -07:00
Nicholas-Westby 29652bb880 Removed a parameter I never ended up using. 2016-04-24 21:54:05 -07:00
Nicholas-Westby 62b7420eaa Prevent dragging when can't add to or remove from list of fieldsets.
Allow dragging into an empty list of fieldsets.
2016-04-24 21:38:59 -07:00
Nicholas-Westby 333f17976b Enable nested dragging. 2016-04-24 17:57:36 -07:00
kjac 45981b0431 Handle lazy load of moment.js 2016-04-23 15:30:14 +02:00
kjac 531ff0aab4 Merge remote-tracking branch 'refs/remotes/origin/fix-publishing-for-collapsed-fieldsets' into allowed-member-groups
# Conflicts:
#	app/views/archetype.default.html
2016-04-23 15:25:33 +02:00
kjac 394572a8fc Yet another stab at fixing it
By tracking the fieldsets that have been expanded (loaded), we can make
sure the submit watchers fire appropriately, even when the fieldsets are
collapsed down again.

Apart from hopefully fixing the publishing issues for collapsed
fieldsets, this also adds a performance gain if the users expand and
collapse the same fieldsets more than once, since the fieldsets now only
load the first time they're expanded (instead of every time).

This also - at least partially - fixes the validation issue #325
introduced by #301
2016-04-23 10:14:56 +02:00
kgiszewski c7114b63f5 Merge branch 'master' of github.com:imulus/Archetype 2016-04-18 11:02:10 -04:00
kgiszewski 9704a8b591 Merge branch 'pr/345' 2016-04-18 11:02:00 -04:00
kjac 0b6af3b4e1 Another stab at fixing publishing for collapsed fieldsets
Make sure we've loaded moment.js before attempting to use it.

Also a small update to styles to accommodate 7.4
2016-04-10 19:23:31 +02:00
kjac 4b874dc5b5 Another stab at fixing publishing for collapsed fieldsets 2016-04-06 20:40:29 +02:00
Kevin Giszewski a081d97546 Update README.md 2016-04-06 09:31:13 -04:00
kjac ebf3fd1135 Clean up duplicate code after merge 2016-04-04 21:32:24 +02:00
kjac 85157612f4 Merge remote-tracking branch 'refs/remotes/origin/fix-publishing-for-collapsed-fieldsets' into allowed-member-groups 2016-04-04 21:31:38 +02:00
kjac 6b79a508bb Fix publishing when all fieldsets are collapsed
Because of the lazy loading of property editors, the
submitWatcherOnSubmit method is not necessarily called when an Archetype
is saved. This is indeed the case when all fieldsets are collapsed.
2016-04-04 21:28:19 +02:00
kjac f57205dab9 More member groups implementation 2016-04-04 21:21:02 +02:00
kjac b6ccab10b3 Merge remote-tracking branch 'refs/remotes/imulus/master' into allowed-member-groups
# Conflicts:
#	app/less/archetype.less
2016-04-04 20:37:15 +02:00
kjac e1f67a738b Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-04-04 20:34:37 +02:00
kgiszewski 4410f1bb81 Bump version to v1.13 2016-04-04 13:08:58 -04:00
kgiszewski 5c2a99987a Fix style so text won't overflow out. 2016-04-04 12:47:39 -04:00
kgiszewski 715a2bf6d5 Fixed missing dialogData from enablePublishing 2016-04-04 12:03:52 -04:00
kjac d9ffb4b097 Merge remote-tracking branch 'refs/remotes/origin/master' into publishing
# Conflicts:
#	app/less/archetype.less
2016-04-03 12:53:30 +02:00
kjac c409922469 Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-04-03 12:43:03 +02:00
kgiszewski 6b40d1e20b Merge branch 'pr/348' 2016-04-02 19:17:51 -04:00
kgiszewski 3e91b1c2c3 Why do I have to keep committing this? 2016-04-02 19:14:30 -04:00
kgiszewski 38eafc0063 Merge branch 'pr/350' 2016-04-02 19:11:43 -04:00
kgiszewski 89aeca9bf0 Add version to json config 2016-04-02 19:11:39 -04:00
kgiszewski 2b6d87d97c Bump version to v1.12.4 2016-04-02 19:10:54 -04:00
kjac 1ca113b455 Fix issue 342 2016-03-31 23:44:52 +02:00
kjac 8228b2dae5 Scope icon styles to fieldset controls only 2016-03-31 08:17:43 +02:00
kjac 22f24ec882 Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-03-31 08:02:33 +02:00
kjac e33eb863e6 #326 - support tags (and other built-in datatypes) 2016-03-29 16:01:14 +02:00
Kevin Giszewski 6bcf291c99 Update README.md 2016-03-29 09:41:05 -04:00
kjac b0f614c891 Allowed member groups PoC 2016-03-23 15:08:07 +01:00
kjac a424a7e4f3 Revert addDefaultProperties to master and adjust addCustomProperties accordingly 2016-03-23 08:38:07 +01:00
kjac 75fa2bb1bb Fix formatting 2016-03-22 19:58:48 +01:00
kjac 5585244d32 Merge remote-tracking branch 'refs/remotes/origin/master' into publishing 2016-03-22 19:40:59 +01:00
kjac 41fa8fa40d Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-03-22 19:38:10 +01:00
kjac 9336f4508a Handle publishing in UTC 2016-03-22 19:35:40 +01:00
kgiszewski f9e5012b4e Merge branch 'master' into pr/338 2016-03-22 11:59:44 -04:00
kgiszewski 61d215e16c Merge branch 'master' of github.com:imulus/Archetype 2016-03-22 11:53:21 -04:00
kgiszewski e1e34be10d Merge branch 'master' into pr/311 2016-03-22 11:36:37 -04:00
Kevin Giszewski 796be76d94 Merge pull request #339 from imulus/feature/74-style
Update style for 7.4
2016-03-21 14:57:49 -04:00
kjac 8f7024c32a Comments 2016-03-20 14:05:31 +01:00
kjac dea307ff8e Filter out fieldsets based on publishing 2016-03-20 13:51:14 +01:00
kjac d69a10de48 Clean up 2016-03-20 13:37:34 +01:00
kjac b93df7a4c0 Add custom properties to new fieldsets 2016-03-20 13:28:22 +01:00
kjac 48dbdebec5 Create expandable settings group and fix icon activation 2016-03-20 13:21:43 +01:00
kjac 65837fa74c Undo a few things 2016-03-20 12:08:23 +01:00
kjac 29a73336e3 Merge remote-tracking branch 'refs/remotes/imulus/master' into publishing 2016-03-20 12:04:52 +01:00
kjac 0dfa8edc95 Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-03-20 12:03:54 +01:00
kjac 0584c4eda5 Prototype (work in progress) 2016-03-20 12:02:21 +01:00
kgiszewski 4eb901fbba Fix #318 2016-03-15 10:04:59 -04:00
Greg Fyans b7875dd850 Added native label for RJP.MultiUrlPicker data type 2016-03-15 10:28:14 +00:00
Kevin Giszewski 19989e556e Update README.md 2016-03-10 12:10:30 -05:00
Kevin Giszewski 9250d66953 Update README.md 2016-03-10 12:07:53 -05:00
kgiszewski fa0b1a4b3b Add a ref required 2016-03-10 11:27:44 -05:00
kgiszewski 73e875e67c Merge branch 'master' into pr/330 2016-03-10 11:19:05 -05:00
kgiszewski e061311689 Add overloads for single partial render and cleanup stuffs 2016-03-10 11:16:27 -05:00
kjac b36f83eaf6 Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-03-05 21:14:47 +01:00
Jamie Gilbert d63f7a6a34 updated angular controller to find view when umbraco is in virtual directory (using relative path) 2016-02-24 17:00:32 +00:00
leekelleher 68c2f55111 Added support to ArchetypePublishedContent for Umbraco extension methods
For the `IPublishedContent` implementation, added support for `GetIndex()`, so that extension methods, such as `IsFirst()`, `IsLast()`, etc will work as expected.

Unfortunately we wont be able to support the `Siblings()`, (or `FollowingSibling`, `PrecedingSibling`) extension methods, as these perform an internal query to the node's parent's children - which in the context of Archetype data is not possible access.

Added unit-tests to support this enhancement.
2016-02-17 13:30:43 +00:00
Jamie Gilbert f22d3cdef3 Modified HTML helper to allow you to render a single fieldset from an Archtype model.
(I Needed to render the first review in a list of review blocks)
2016-02-05 14:33:02 +00:00
kgiszewski 13b59d0d61 Bump version to v1.12.3 2016-02-04 11:20:44 -05:00
kjac 188c09d3c1 Fix issue #323
Made the config dialogs do "live editing" instead of working on a copy
of the config model.
2016-01-23 14:56:28 +01:00
kjac 6d8770907c Fix path to courier project
The gruntfile had a wrong path to the Courier project, which messed up
the grunt setup.
2016-01-23 14:55:11 +01:00
kjac efbed9606d Merge remote-tracking branch 'refs/remotes/imulus/master' 2016-01-23 10:31:06 +01:00
leekelleher c862ecc36f Fixes #319 - Grunt/MSBuild
Sets the MSBuild project config from "Debug" to "Release".
2016-01-13 12:26:19 +00:00
bjarnef 523630416f Correct for attribute to match id of input
... futhermore add title tooltip with value of property alias like in
Umbraco core.
2016-01-05 22:19:08 +01:00
kgiszewski 990836bc37 Fix #315 2016-01-05 08:39:09 -05:00
kgiszewski bb194fff76 Fix #314 2016-01-05 08:35:35 -05:00
kgiszewski 16351df692 Fix #312 2016-01-04 15:02:02 -05:00
kgiszewski 213d3940ca Merge branch 'pr/310' 2015-12-15 11:26:52 -05:00
kgiszewski 8dfe1f3ca4 Keepin it DRY 2015-12-15 11:26:40 -05:00
kgiszewski 3291998171 Merge branch 'master' into pr/308 2015-12-15 11:04:18 -05:00
Martin Abrahams 7df4d4cfcd Fix for issue #258, same issue as fileupload datatype, need to add empty validation property 2015-12-10 16:03:14 +11:00
kjac 6494327c77 Merge remote-tracking branch 'refs/remotes/imulus/master' 2015-11-29 17:04:39 +01:00
Tom Fulton 293aa7f6f3 Update grunt-umbraco-package to v1.0 2015-11-24 21:54:01 -08:00
68 changed files with 2890 additions and 1081 deletions
+2 -1
View File
@@ -62,4 +62,5 @@ VersionInfo.cs
.builds
.svn
.hg
.hgignore
.hgignore
app/Umbraco/.vs/config/applicationhost.config
+74 -35
View File
@@ -18,8 +18,7 @@ module.exports = function(grunt) {
"app/views/archetype.config.fieldset.dialog_versioned.html": "app/views/archetype.config.fieldset.dialog.html",
"app/views/archetype.config_versioned.html": "app/views/archetype.config.html",
"app/views/archetype_versioned.html": "app/views/archetype.html",
"app/views/archetype.default_versioned.html": "app/views/archetype.default.html",
"app/views/archetype.default_versioned.html": "app/views/archetype.default.html"
},
options: {
replacements: [{
@@ -86,6 +85,7 @@ module.exports = function(grunt) {
'app/controllers/controller_versioned.js',
'app/controllers/config.controller.js',
'app/controllers/config.dialog.controller.js',
'app/controllers/config.global.controller.js',
'app/directives/archetypeproperty.js',
'app/directives/archetypesubmitwatcher.js',
'app/directives/archetypecustomview.js',
@@ -96,7 +96,8 @@ module.exports = function(grunt) {
'app/resources/archetypePropertyEditorResource.js',
'app/services/archetypeService.js',
'app/services/archetypeLabelService.js',
'app/services/archetypeCacheService.js'
'app/services/archetypeCacheService.js',
'app/services/archetypeGlobalConfigService.js'
],
dest: '<%= basePath %>/js/archetype.js'
}
@@ -126,7 +127,7 @@ module.exports = function(grunt) {
expand: true
},
dll: {
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Debug/',
cwd: 'app/Umbraco/Umbraco.Archetype/bin/Release/',
src: 'Archetype.dll',
dest: '<%= dest %>/bin/',
expand: true
@@ -152,7 +153,13 @@ module.exports = function(grunt) {
{
cwd: '<%= dest %>/bin',
src: ['*.dll'],
dest: 'tmp/nuget/lib/net40',
dest: 'tmp/nuget_binaries/lib/net40',
expand: true
},
{
cwd: 'app/Umbraco/Archetype.Courier/bin/Release/',
src: ['Archetype.Courier.dll'],
dest: 'tmp/nuget_courier/lib/net40',
expand: true
}
]
@@ -169,6 +176,14 @@ module.exports = function(grunt) {
dist: {
src: 'tmp/nuget/package.nuspec',
dest: 'pkg'
},
dist_binaries: {
src: 'tmp/nuget_binaries/package_binaries.nuspec',
dest: 'pkg'
},
dist_courier: {
src: 'tmp/nuget_courier/package_courier.nuspec',
dest: 'pkg'
}
},
@@ -182,29 +197,61 @@ module.exports = function(grunt) {
license: '<%= pkgMeta.license %>',
licenseUrl: '<%= pkgMeta.licenseUrl %>',
author: '<%= pkgMeta.author %>',
authorUrl: '<%= pkgMeta.authorUrl %>',
files: [{ path: 'tmp/nuget/**', target: 'content/App_Plugins/Archetype'}]
authorUrl: '<%= pkgMeta.authorUrl %>'
}
},
'files': {
'tmp/nuget/package.nuspec': ['config/package.nuspec']
}
},
'nuspec_binaries': {
'options': {
'data': {
name: '<%= pkgMeta.name %>.Binaries',
version: '<%= pkgMeta.version %>',
url: '<%= pkgMeta.url %>',
license: '<%= pkgMeta.license %>',
licenseUrl: '<%= pkgMeta.licenseUrl %>',
author: '<%= pkgMeta.author %>',
authorUrl: '<%= pkgMeta.authorUrl %>'
}
},
'files': {
'tmp/nuget_binaries/package_binaries.nuspec': ['config/package_binaries.nuspec']
}
},
'nuspec_courier': {
'options': {
'data': {
name: '<%= pkgMeta.name %>.Courier',
version: '<%= pkgMeta.version %>',
url: '<%= pkgMeta.url %>',
license: '<%= pkgMeta.license %>',
licenseUrl: '<%= pkgMeta.licenseUrl %>',
author: '<%= pkgMeta.author %>',
authorUrl: '<%= pkgMeta.authorUrl %>'
}
},
'files': {
'tmp/nuget_courier/package_courier.nuspec': ['config/package_courier.nuspec']
}
}
},
umbracoPackage: {
options: {
name: "<%= pkgMeta.name %>",
version: '<%= pkgMeta.version %>',
url: '<%= pkgMeta.url %>',
license: '<%= pkgMeta.license %>',
licenseUrl: '<%= pkgMeta.licenseUrl %>',
author: '<%= pkgMeta.author %>',
authorUrl: '<%= pkgMeta.authorUrl %>',
manifest: 'config/package.xml',
readme: 'config/readme.txt',
sourceDir: 'tmp/umbraco',
outputDir: 'pkg',
dist: {
src: 'tmp/umbraco',
dest: 'pkg',
options: {
name: "<%= pkgMeta.name %>",
version: '<%= pkgMeta.version %>',
url: '<%= pkgMeta.url %>',
license: '<%= pkgMeta.license %>',
licenseUrl: '<%= pkgMeta.licenseUrl %>',
author: '<%= pkgMeta.author %>',
authorUrl: '<%= pkgMeta.authorUrl %>',
readme: '<%= grunt.file.read("config/readme.txt") %>'
}
}
},
@@ -224,7 +271,8 @@ module.exports = function(grunt) {
'app/controllers/*.js',
'!app/controllers/controller.js',
'!app/controllers/config.controller.js',
'!app/controllers/config.dialog.controller.js'
'!app/controllers/config.dialog.controller.js',
'!app/controllers/config.global.controller.js'
],
less: [
'app/less/*.less',
@@ -234,7 +282,7 @@ module.exports = function(grunt) {
assemblyinfo: {
options: {
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj', 'app/Umbraco/Umbraco.Archetype/Archetype.Courier.csproj'],
files: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj', 'app/Umbraco/Archetype.Courier/Archetype.Courier.csproj'],
filename: 'VersionInfo.cs',
info: {
version: '<%= (pkgMeta.version.indexOf("-") > 0 ? pkgMeta.version.substring(0, pkgMeta.version.indexOf("-")) : pkgMeta.version) %>',
@@ -248,15 +296,6 @@ module.exports = function(grunt) {
src: ['<%= grunt.option("target") %>\\Web.config']
}
},
jshint: {
options: {
jshintrc: '.jshintrc'
},
src: {
src: ['app/**/*.js', 'lib/**/*.js']
}
},
msbuild: {
options: {
@@ -272,7 +311,7 @@ module.exports = function(grunt) {
dist: {
src: ['app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj','app/Umbraco/Archetype.Courier/Archetype.Courier.csproj'],
options: {
projectConfiguration: 'Debug',
projectConfiguration: 'Release',
targets: ['Clean', 'Rebuild'],
}
}
@@ -280,8 +319,8 @@ module.exports = function(grunt) {
});
grunt.registerTask('default', ['clean', 'string-replace', 'less', 'concat', 'assemblyinfo', 'msbuild:dist', 'copy:dll', 'copy:assets', 'copy:html', 'copy:config', 'clean:html', 'clean:js', 'clean:less']);
grunt.registerTask('nuget', ['clean:tmp', 'default', 'copy:nuget', 'template:nuspec', 'nugetpack', 'clean:tmp']);
grunt.registerTask('umbraco', ['clean:tmp', 'default', 'copy:umbraco', 'umbracoPackage', 'clean:tmp']);
grunt.registerTask('package', ['clean:tmp', 'default', 'copy:nuget', 'template:nuspec', 'nugetpack', 'copy:umbraco', 'umbracoPackage', 'clean:tmp']);
grunt.registerTask('nuget', ['copy:nuget', 'template:nuspec', 'template:nuspec_binaries', 'template:nuspec_courier', 'nugetpack']);
grunt.registerTask('umbraco', ['copy:umbraco', 'umbracoPackage']);
grunt.registerTask('package', ['clean:tmp', 'default', 'nuget', 'copy:umbraco', 'umbracoPackage', 'clean:tmp']);
grunt.registerTask('assets', ['clean', 'string-replace', 'less', 'concat', 'assemblyinfo', 'copy:assets', 'copy:html', 'copy:config', 'clean:html', 'clean:js', 'clean:less']);
};
+13
View File
@@ -0,0 +1,13 @@
# Information Collection Disclosure
As of version v1.16.0, we are checking your installed version of Archetype against the current version. In this process we collect the current version of Archetype along with the current version of Umbraco that you are running. We use these values to help determine a response message to you. You may opt-out of this process by 'un-checking' the option in any of the Archetypes you have configured in the `Developer->Data Types` section of Umbraco.
![opt out](assets/optout3.png)
This is a global setting that will set an `AppSetting` and update a file located at `~/config/archetype.config.js`. If you manually change the setting it will require an app reload to refresh to runtime values. If somehow this file becomes corrupt, a new file will be generated and you will again have to opt out.
We identify your install only by a randomly generated GUID. We WILL NOT store your IP address or hostname during the update check.
Part of the reason we collect this information is to also ascertain how many active installs exist. If this number is sufficiently high, we can plan accordingly and attempt to keep this project going.
We would ask that you reach out to the Archetype team via creating an issue on this site if you have any questions or concerns. We truly want Archetype to be a win-win for all involved.
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2014 Imulus
Copyright (c) 2016 Kevin Giszewski LLC
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
+23 -4
View File
@@ -1,18 +1,37 @@
Archetype
=========
![alt tag](http://imulus.github.io/Archetype/images/logo.png)
![alt tag](http://kgiszewski.github.io/Archetype/images/logo.png)
![alt tag](http://imulus.github.io/Archetype/images/example1.png)
![alt tag](http://kgiszewski.github.io/Archetype/images/example1.png)
## Installation
Install the selected <a href='https://github.com/imulus/Archetype/releases'>release</a> through the Umbraco package installer or via <a href='http://www.nuget.org/packages/Archetype/'>NuGet</a>.
Install the selected <a href='https://github.com/kgiszewski/Archetype/releases'>release</a> through the Umbraco package installer or via <a href='http://www.nuget.org/packages/Archetype/'>NuGet</a>.
## Official Docs ##
https://github.com/kgiszewski/ArchetypeManual
Get up and running in 15 minutes! https://www.youtube.com/watch?v=79LksNwGjLk
## News and Updates ##
Follow us on Twitter https://twitter.com/ArchetypeKit
## Core Team ##
* Kevin Giszewski (founder/project lead) - Tonic - https://kevin.giszewski.com/
* Tom Fulton (founder) - Tonic - http://hellotonic.com/
* Lee Kelleher - Umbrella - http://www.umbrellainc.co.uk/
* Matt Brailsford - The Outfield - http://www.theoutfield.co.uk/
* Kenn Jacobsen - Vertica - http://kennjacobsen.dk/
## Sponsor us\Donate!
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L)
This project is funded by the core team members' time only. We don't charge for Archetype but it does take quite a bit of effort to keep it up-to-date with Umbraco core changes. If you're making a few bucks off of Archetype, we wouldn't refuse a donation :)
[Learn more](Sponsors.md) about sponsorship!
## Information Collection Disclosure
Please read the information disclosure [here](Information%20Collection%20Disclosure.md).
## Contribute ##
Want to contribute to Archetype? You'll want to use Grunt (our task runner) to help you integrate with a local copy of Umbraco.
+13
View File
@@ -0,0 +1,13 @@
# Sponsorship
Are you a company that depends on Archetype? We would love for you to sponsor us! Here's some suggested ways below!
## Sponsor a Sprint
We have a [backlog](https://github.com/kgiszewski/Archetype/issues), it gets worked on when either we have a personal need, we get bored or when we get a sponsorship. If you want to sponsor a sprint, we can give you thanks on social media and if you're really generous, we can put your logo and link on a well placed spot in a version release. [Contact us](https://twitter.com/ArchetypeKit) to get started.
## Donations
If you want to quietly support us, you can also send us a donation:
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L)
@@ -163,6 +163,7 @@
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll</HintPath>
@@ -262,6 +263,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PropertyValueConverter\PropertyValueConverterTests.cs" />
<Compile Include="PublishedContent\ArchetypePublishedContentTests.cs" />
<Compile Include="PublishedContent\TypeConverterTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@@ -91,5 +91,66 @@ namespace Archetype.Tests.PublishedContent
Assert.Throws<ArgumentNullException>(code);
}
[Test]
public void ArchetypePublishedContent_GetIndex()
{
var contentSet = _archetype.ToPublishedContentSet();
var i = 0;
foreach (var content in contentSet)
{
Assert.AreEqual(content.GetIndex(), i);
i++;
}
}
[Test]
public void ArchetypePublishedContentSet_IsFirstIsLast()
{
var contentSet = _archetype.ToPublishedContentSet();
foreach (var content in contentSet)
{
var value = content.GetPropertyValue<string>("boxHeadline");
Assert.That(value == "Box 1 Title", Is.EqualTo(content.IsFirst()));
Assert.That(value == "Another Box", Is.EqualTo(content.IsLast()));
}
}
[Test]
public void ArchetypePublishedContentSet_PreviousNext()
{
var contentSet = _archetype.ToPublishedContentSet();
var list = contentSet.ToList();
Assert.That(list.Count, Is.EqualTo(2));
var first = list[0];
var last = list[1];
var next = first.Next();
Assert.AreEqual(next, last);
var prev = last.Previous();
Assert.AreEqual(prev, first);
}
[Test, ExpectedException(typeof(NullReferenceException))]
public void ArchetypePublishedContentSet_Siblings()
{
var contentSet = _archetype.ToPublishedContentSet();
var content = contentSet.FirstOrDefault();
var siblings = content.Siblings();
Assert.That(siblings, Is.Not.Null);
var following = content.FollowingSibling();
Assert.That(following, Is.Not.Null);
var preceding = content.PrecedingSibling();
Assert.That(preceding, Is.Not.Null);
}
}
}
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Models;
using Archetype.PropertyConverters;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
namespace Archetype.Tests.PublishedContent
{
[TestFixture]
public class TypeConverterTests
{
private ArchetypeModel _archetype;
[TestFixtureSetUp]
public void Init()
{
var archetypeJson = System.IO.File.ReadAllText("..\\..\\Data\\sample-1.json");
var converter = new ArchetypeValueConverter();
_archetype = (ArchetypeModel)converter.ConvertDataToSource(null, archetypeJson, false);
}
[TestCase(typeof(ArchetypeModel), true)]
[TestCase(typeof(ArchetypePublishedContentSet), true)]
[TestCase(typeof(IEnumerable<IPublishedContent>), true)]
[TestCase(typeof(string), true)]
[TestCase(typeof(int), false)]
[TestCase(typeof(ArchetypeFieldsetModel), false)]
public void ArchetypeModel_ConvertsTo_EnumerablePublishedContent(Type destinationType, bool expected)
{
Assert.IsNotNull(_archetype);
var attempt = _archetype.TryConvertTo(destinationType);
Assert.That(attempt.Success, Is.EqualTo(expected));
if (attempt.Success)
{
Assert.IsNotNull(attempt.Result);
Assert.That(attempt.Result, Is.InstanceOf(destinationType));
}
}
[TestCase(typeof(ArchetypeFieldsetModel), true)]
[TestCase(typeof(ArchetypePublishedContent), true)]
[TestCase(typeof(IPublishedContent), true)]
[TestCase(typeof(string), true)]
[TestCase(typeof(int), false)]
[TestCase(typeof(ArchetypeModel), false)]
public void ArchetypeFieldsetModel_ConvertsTo_PublishedContent(Type destinationType, bool expected)
{
CollectionAssert.IsNotEmpty(_archetype.Fieldsets);
var attempt = _archetype.First().TryConvertTo(destinationType);
Assert.That(attempt.Success, Is.EqualTo(expected));
if (attempt.Success)
{
Assert.IsNotNull(attempt.Result);
Assert.That(attempt.Result, Is.InstanceOf(destinationType));
}
}
}
}
-53
View File
@@ -1,53 +0,0 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Logging;
namespace DatabaseSizer
{
/// <summary>
/// A now obsolete project that handled an Umbraco core limitation.
/// </summary>
[Obsolete("This project is now obsolete with 7.2.2+")]
public class Application : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
base.ApplicationStarted(umbracoApplication, applicationContext);
ExpandPrevalueValueColumnSize();
}
protected void ExpandPrevalueValueColumnSize()
{
try
{
var dbContext = ApplicationContext.Current.DatabaseContext;
var colCount =
dbContext.Database.ExecuteScalar<int>(
"SELECT COUNT(1) FROM INFORMATION_SCHEMA.COLUMNS WHERE DATA_TYPE = 'nvarchar' AND COLUMN_NAME = 'value' AND CHARACTER_MAXIMUM_LENGTH = 2500 AND TABLE_NAME = 'cmsDataTypePreValues'");
// Check column
if (colCount != 0)
{
using (var trans = dbContext.Database.GetTransaction())
{
// Change column
dbContext.Database.Execute("ALTER TABLE [cmsDataTypePreValues] ALTER COLUMN [value] ntext NULL;");
trans.Complete();
}
LogHelper.Debug(typeof(Application), "Successfully expanded Prevalue table Value column");
}
else
{
LogHelper.Debug(typeof(Application), "Prevalue table Value column is already expanded");
}
}
catch (Exception ex)
{
LogHelper.Error(typeof(Application), "Error expanding Prevalue table Value column", ex);
}
}
}
}
@@ -1,250 +0,0 @@
<?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>{0114C963-C514-49C1-B7AB-DCB1825F498C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DatabaseSizer</RootNamespace>
<AssemblyName>DatabaseSizer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
</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="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>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>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>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>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>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>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>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>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>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" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<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>
<Compile Include="Application.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</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>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DatabaseSizer.cs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DatabaseSizer.cs")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("28dc35d2-3dfb-40b4-9093-bc47c91127ea")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
-27
View File
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
-25
View File
@@ -1,25 +0,0 @@
<?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.9.0.0" targetFramework="net45" />
<package id="ImageProcessor.Web" version="3.2.3.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>
+3 -7
View File
@@ -1,6 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
# Visual Studio 2013
VisualStudioVersion = 12.0.40629.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Umbraco", "Umbraco.Archetype\Archetype.Umbraco.csproj", "{7D185D41-4228-4978-ACB8-83F9A48AD94F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{D84AA4ED-85A6-484F-9E72-BE7AC9835821}"
@@ -12,8 +14,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{D84AA4
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Archetype.Tests", "Archetype.Tests\Archetype.Tests.csproj", "{21F3E6CF-B76F-4059-9474-1AF1CE63CD6B}"
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
@@ -30,10 +30,6 @@ Global
{21F3E6CF-B76F-4059-9474-1AF1CE63CD6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21F3E6CF-B76F-4059-9474-1AF1CE63CD6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21F3E6CF-B76F-4059-9474-1AF1CE63CD6B}.Release|Any CPU.Build.0 = Release|Any CPU
{0114C963-C514-49C1-B7AB-DCB1825F498C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
@@ -1,9 +1,7 @@
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Web.Http;
using AutoMapper;
using Umbraco.Core.Models;
@@ -11,32 +9,57 @@ using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Umbraco.Web.Editors;
using Archetype.Extensions;
using Archetype.Models;
namespace Archetype.Api
{
/// <summary>
/// Controller that handles datatype related interactions.
/// </summary>
/// <seealso cref="Umbraco.Web.Editors.UmbracoAuthorizedJsonController" />
[PluginController("ArchetypeApi")]
public class ArchetypeDataTypeController : UmbracoAuthorizedJsonController
{
private static DateTime _lastVersionCheck;
private const int IntervalInDaysBetweenVersionChecks = 7;
public IEnumerable<object> GetAllPropertyEditors()
{
return
global::Umbraco.Core.PropertyEditors.PropertyEditorResolver.Current.PropertyEditors
.Select(x => new {defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View});
.Select(x => new { defaultPreValues = x.DefaultPreValuesForArchetype(), alias = x.Alias, view = x.ValueEditor.View });
}
/// <summary>
/// Gets all datatypes.
/// </summary>
/// <returns></returns>
public object GetAll()
/// <returns>System.Object.</returns>
public object GetAll()
{
var dataTypes = Services.DataTypeService.GetAllDataTypeDefinitions();
return dataTypes.Select(t => new { guid = t.Key, name = t.Name });
}
/// <summary>
/// Gets all details.
/// </summary>
/// <returns>System.Object.</returns>
public object GetAllDetails()
{
var dataTypes = Services.DataTypeService.GetAllDataTypeDefinitions();
var list = new List<object>();
foreach (var dataType in dataTypes)
{
var dataTypeDisplay = Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
list.Add(new { selectedEditor = dataTypeDisplay.SelectedEditor, preValues = dataTypeDisplay.PreValues, dataTypeGuid = dataType.Key });
}
return list;
}
/// <summary>
/// Gets the datatype by GUID.
/// </summary>
@@ -68,11 +91,14 @@ namespace Archetype.Api
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 };
}
@@ -82,19 +108,64 @@ namespace Archetype.Api
/// <returns></returns>
public object GetDllVersion()
{
return new {dllVersion = _version()};
return new { dllVersion = ArchetypeHelper.Instance.DllVersion() };
}
/// <summary>
/// Gets the DLL version from the file.
/// Globals the settings.
/// </summary>
/// <returns></returns>
private string _version()
/// <returns>System.Object.</returns>
[HttpGet]
public object GlobalSettings()
{
var asm = Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(asm.Location);
return new
{
isCheckingForUpdates = ArchetypeGlobalSettings.Instance.CheckForUpdates
};
}
return fvi.FileVersion;
/// <summary>
/// Sets the check for updates.
/// </summary>
/// <param name="isChecking">if set to <c>true</c> [is checking].</param>
[HttpPost]
public void SetCheckForUpdates([FromBody] bool isChecking)
{
ArchetypeGlobalSettings.Instance.CheckForUpdates = isChecking;
ArchetypeGlobalSettings.Instance.Save();
}
/// <summary>
/// Checks for updates.
/// </summary>
/// <returns>System.Object.</returns>
[HttpPost]
public object CheckForUpdates()
{
if (!ArchetypeGlobalSettings.Instance.CheckForUpdates || !IsItTimeToCheck())
{
return new
{
isUpdateAvailable = false
};
}
var updateNotificationModel = ArchetypeHelper.Instance.CheckForUpdates();
_lastVersionCheck = DateTime.UtcNow;
return new
{
isUpdateAvailable = updateNotificationModel.IsUpdateAvailable,
headline = updateNotificationModel.Headline,
type = updateNotificationModel.Type,
message = updateNotificationModel.Message,
url = updateNotificationModel.Url
};
}
internal bool IsItTimeToCheck()
{
return _lastVersionCheck.AddDays(IntervalInDaysBetweenVersionChecks) < DateTime.UtcNow;
}
}
}
@@ -129,6 +129,7 @@
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<Private>False</Private>
@@ -238,6 +239,8 @@
<Compile Include="Extensions\ArchetypePropertyModelExtensions.cs" />
<Compile Include="Extensions\PropertyEditorExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Models\ArchetypeConfigFileModel.cs" />
<Compile Include="Models\ArchetypeGlobalSettings.cs" />
<Compile Include="Models\ArchetypeModel.cs" />
<Compile Include="Models\ArchetypePreValue.cs" />
<Compile Include="Models\ArchetypePreValueFieldset.cs" />
@@ -248,10 +251,13 @@
<Compile Include="Models\ArchetypePublishedContent.cs" />
<Compile Include="Models\ArchetypePublishedContentSet.cs" />
<Compile Include="Models\ArchetypePublishedProperty.cs" />
<Compile Include="Models\ArchetypeUpdateNotification.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\VersionInfo.cs" />
<Compile Include="PropertyConverters\ArchetypeValueConverter.cs" />
<Compile Include="PropertyEditors\ArchetypePropertyEditor.cs" />
<Compile Include="TypeConverters\ArchetypeFieldsetModelConverter.cs" />
<Compile Include="TypeConverters\ArchetypeModelConverter.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
@@ -12,5 +12,8 @@
public const string CacheKey_DataTypeByGuid = "";
public const string CacheKey_PreValueFromDataTypeId = "Archetype_GetArchetypePreValueFromDataTypeId_";
public const string UmbracoVersionAlias = "umbracoConfigurationStatus";
public const string NotificationUrl = "https://api.gizmo42.com/v1/archetype/check-for-updates";
}
}
@@ -1,4 +1,5 @@
using Archetype.Models;
using System.Linq;
using Archetype.Models;
using Umbraco.Core.Models;
namespace Archetype.Extensions
@@ -9,5 +10,16 @@ namespace Archetype.Extensions
{
return new ArchetypePublishedContent(fieldset);
}
public static IPublishedContent ToPublishedContent(this ArchetypeFieldsetModel fieldset, ArchetypeModel archetype)
{
var contentSet = archetype.ToPublishedContentSet();
var first = contentSet
.Cast<ArchetypePublishedContent>()
.FirstOrDefault(x => x.ArchetypeFieldset == fieldset);
return first ?? new ArchetypePublishedContent(fieldset);
}
}
}
@@ -1,12 +1,21 @@
using System;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using System.Text;
using Archetype.Models;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using System.Reflection;
using System.Diagnostics;
using System.Net;
/// <summary>
/// The Extensions namespace.
/// </summary>
namespace Archetype.Extensions
{
/// <summary>
@@ -14,20 +23,52 @@ namespace Archetype.Extensions
/// </summary>
public class ArchetypeHelper
{
/// <summary>
/// The json settings
/// </summary>
protected JsonSerializerSettings _jsonSettings;
/// <summary>
/// The application
/// </summary>
protected ApplicationContext _app;
private static readonly ArchetypeHelper _instance = new ArchetypeHelper();
internal static ArchetypeHelper Instance { get { return _instance; } }
/// <summary>
/// The pad lock
/// </summary>
private static readonly object _padLock = new object();
/// <summary>
/// The instance
/// </summary>
private static ArchetypeHelper _instance = new ArchetypeHelper();
/// <summary>
/// Initializes a new instance of the <see cref="ArchetypeHelper"/> class.
/// Gets the instance.
/// </summary>
internal ArchetypeHelper()
/// <value>The instance.</value>
internal static ArchetypeHelper Instance {
get
{
if (_instance == null)
{
lock (_padLock)
{
if (_instance == null)
{
_instance = new ArchetypeHelper();
}
}
}
return _instance;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="ArchetypeHelper" /> class.
/// </summary>
private ArchetypeHelper()
{
var dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
dcr.DefaultMembersSearchFlags |= BindingFlags.NonPublic;
_jsonSettings = new JsonSerializerSettings { ContractResolver = dcr };
_app = ApplicationContext.Current;
@@ -36,9 +77,7 @@ namespace Archetype.Extensions
/// <summary>
/// Gets the json serializer settings.
/// </summary>
/// <value>
/// The json serializer settings.
/// </value>
/// <value>The json serializer settings.</value>
internal JsonSerializerSettings JsonSerializerSettings { get { return _jsonSettings; } }
/// <summary>
@@ -46,7 +85,7 @@ namespace Archetype.Extensions
/// </summary>
/// <param name="sourceJson">The source JSON.</param>
/// <param name="dataTypePreValues">The data type pre values.</param>
/// <returns></returns>
/// <returns>ArchetypeModel.</returns>
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, PreValueCollection dataTypePreValues)
{
try
@@ -78,7 +117,7 @@ namespace Archetype.Extensions
/// <param name="sourceJson">The source JSON.</param>
/// <param name="dataTypeId">The data type identifier.</param>
/// <param name="hostContentType">Type of the host content.</param>
/// <returns></returns>
/// <returns>ArchetypeModel.</returns>
internal ArchetypeModel DeserializeJsonToArchetype(string sourceJson, int dataTypeId, PublishedContentType hostContentType = null)
{
try
@@ -98,7 +137,7 @@ namespace Archetype.Extensions
return archetype;
}
catch
catch (Exception ex)
{
return new ArchetypeModel();
}
@@ -108,21 +147,66 @@ namespace Archetype.Extensions
/// Determines whether datatypeId has had it's PVC overridden.
/// </summary>
/// <param name="dataTypeId">The data type identifier.</param>
/// <returns></returns>
/// <returns><c>true</c> if [is property value converter overridden] [the specified data type identifier]; otherwise, <c>false</c>.</returns>
internal bool IsPropertyValueConverterOverridden(int dataTypeId)
{
var prevalues = GetArchetypePreValueFromDataTypeId(dataTypeId);
if (prevalues == null)
return false;
return prevalues.OverrideDefaultPropertyValueConverter;
}
/// <summary>
/// Checks for updates.
/// </summary>
/// <returns>ArchetypeUpdateNotification.</returns>
internal ArchetypeUpdateNotification CheckForUpdates()
{
try
{
using (var client = new HttpClient())
{
var content = new StringContent(JsonConvert.SerializeObject(new
{
umbracoVersion = ConfigurationManager.AppSettings[Constants.UmbracoVersionAlias],
archetypeVersion = DllVersion(),
id = ArchetypeGlobalSettings.Instance.Id
}), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("x-api-key-id", ArchetypeGlobalSettings.Instance.ApiKey.ToString());
var response = client.PostAsync(new Uri(Constants.NotificationUrl), content).Result;
if (response.StatusCode == HttpStatusCode.OK)
{
var responseString = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<ArchetypeUpdateNotification>(responseString);
}
return new ArchetypeUpdateNotification
{
IsUpdateAvailable = false
};
}
}
catch (Exception ex)
{
//if anything goes wrong let's make sure we don't break their site
return new ArchetypeUpdateNotification
{
IsUpdateAvailable = false
};
}
}
/// <summary>
/// Gets the archetype pre value from data type identifier.
/// </summary>
/// <param name="dataTypeId">The data type identifier.</param>
/// <returns></returns>
/// <returns>ArchetypePreValue.</returns>
private ArchetypePreValue GetArchetypePreValueFromDataTypeId(int dataTypeId)
{
return _app.ApplicationCache.RuntimeCache.GetCacheItem(
@@ -147,7 +231,7 @@ namespace Archetype.Extensions
/// Gets the archetype pre value from pre values collection.
/// </summary>
/// <param name="dataTypePreValues">The data type pre values.</param>
/// <returns></returns>
/// <returns>ArchetypePreValue.</returns>
private ArchetypePreValue GetArchetypePreValueFromPreValuesCollection(PreValueCollection dataTypePreValues)
{
var preValueAsString = dataTypePreValues.PreValuesAsDictionary.First().Value.Value;
@@ -159,7 +243,7 @@ namespace Archetype.Extensions
/// Gets the data type by unique identifier.
/// </summary>
/// <param name="guid">The unique identifier.</param>
/// <returns></returns>
/// <returns>IDataTypeDefinition.</returns>
internal IDataTypeDefinition GetDataTypeByGuid(Guid guid)
{
return (IDataTypeDefinition)ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
@@ -172,6 +256,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>
/// <param name="hostContentType">Type of the host content.</param>
private void RetrieveAdditionalProperties(ref ArchetypeModel archetype, ArchetypePreValue preValue, PublishedContentType hostContentType = null)
{
foreach (var fieldset in preValue.Fieldsets)
@@ -197,7 +282,6 @@ namespace Archetype.Extensions
/// <summary>
/// Retrieves additional metadata that isn't available on the stored model of an ArchetypePreValue
/// </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 ArchetypePreValue preValue)
{
@@ -209,5 +293,18 @@ namespace Archetype.Extensions
}
}
}
/// <summary>
/// Gets the DLL version from the file.
/// </summary>
/// <returns>System.String.</returns>
internal string DllVersion()
{
var asm = Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(asm.Location);
return fvi.FileVersion;
}
}
}
@@ -12,6 +12,103 @@ namespace Archetype.Extensions
/// </summary>
public static class HtmlHelperExtensions
{
/// <summary>
/// Renders the partials based on the model, partial path and given viewdata dictionary.
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="archetypeModel">The archetype model.</param>
/// <param name="partialPath">The partial path.</param>
/// <param name="viewDataDictionary">The view data dictionary.</param>
/// <returns></returns>
private static IHtmlString _renderPartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
var sb = new StringBuilder();
foreach (var fieldsetModel in archetypeModel)
{
sb.AppendLine(_renderPartial(htmlHelper, fieldsetModel, partialPath, viewDataDictionary).ToString());
}
return new HtmlString(sb.ToString());
}
/// <summary>
/// Renders the fieldset partial
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="fieldsetModel"></param>
/// <param name="partialPath">The partial path.</param>
/// <param name="viewDataDictionary">The view data dictionary.</param>
/// <returns></returns>
private static IHtmlString _renderPartial(HtmlHelper htmlHelper, ArchetypeFieldsetModel fieldsetModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
var context = HttpContext.Current;
if (fieldsetModel == null || context == null)
{
return new HtmlString("");
}
var sb = new StringBuilder();
//default
var pathToPartials = "~/Views/Partials/Archetype/";
if (!string.IsNullOrEmpty(partialPath))
{
pathToPartials = partialPath;
}
var partial = string.Format("{0}{1}.cshtml", pathToPartials, fieldsetModel.Alias);
if (System.IO.File.Exists(context.Server.MapPath(partial)))
{
sb.AppendLine(htmlHelper.Partial(partial, fieldsetModel, viewDataDictionary).ToString());
}
else
{
LogHelper.Info<ArchetypeModel>(string.Format("The partial for {0} could not be found. Please create a partial with that name or rename your alias.", context.Server.MapPath(partial)));
}
return new HtmlString(sb.ToString());
}
/// <summary>
/// Renders a single archtype partial from a fieldset
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="fieldsetModel">The fieldset model.</param>
/// <returns></returns>
public static IHtmlString RenderArchetypePartial(this HtmlHelper htmlHelper, ArchetypeFieldsetModel fieldsetModel)
{
return _renderPartial(htmlHelper, fieldsetModel, null, null);
}
/// <summary>
/// Renders the archetype partial.
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="fieldsetModel">The fieldset model.</param>
/// <param name="partialView">The partial view.</param>
/// <returns></returns>
public static IHtmlString RenderArchetypePartial(this HtmlHelper htmlHelper, ArchetypeFieldsetModel fieldsetModel, string partialView)
{
return _renderPartial(htmlHelper, fieldsetModel, partialView, null);
}
/// <summary>
/// Renders the archetype partial.
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="fieldsetModel">The fieldset model.</param>
/// <param name="partialView">The partial view.</param>
/// <param name="viewDataDictionary">The view data dictionary.</param>
/// <returns></returns>
public static IHtmlString RenderArchetypePartial(this HtmlHelper htmlHelper, ArchetypeFieldsetModel fieldsetModel, string partialView, ViewDataDictionary viewDataDictionary)
{
return _renderPartial(htmlHelper, fieldsetModel, partialView, viewDataDictionary);
}
/// <summary>
/// Renders the archetype partials.
/// </summary>
@@ -20,7 +117,7 @@ namespace Archetype.Extensions
/// <returns></returns>
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel)
{
return RenderPartials(htmlHelper, archetypeModel, null, null);
return _renderPartials(htmlHelper, archetypeModel, null, null);
}
/// <summary>
@@ -32,7 +129,7 @@ namespace Archetype.Extensions
/// <returns></returns>
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath)
{
return RenderPartials(htmlHelper, archetypeModel, partialPath, null);
return _renderPartials(htmlHelper, archetypeModel, partialPath, null);
}
/// <summary>
@@ -44,7 +141,7 @@ namespace Archetype.Extensions
/// <returns></returns>
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, ViewDataDictionary viewDataDictionary)
{
return RenderPartials(htmlHelper, archetypeModel, null, viewDataDictionary);
return _renderPartials(htmlHelper, archetypeModel, null, viewDataDictionary);
}
/// <summary>
@@ -57,49 +154,7 @@ namespace Archetype.Extensions
/// <returns></returns>
public static IHtmlString RenderArchetypePartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
return htmlHelper.RenderPartials(archetypeModel, partialPath, viewDataDictionary);
}
/// <summary>
/// Renders the partials based on the model, partial path and given viewdata dictionary.
/// </summary>
/// <param name="htmlHelper">The HTML helper.</param>
/// <param name="archetypeModel">The archetype model.</param>
/// <param name="partialPath">The partial path.</param>
/// <param name="viewDataDictionary">The view data dictionary.</param>
/// <returns></returns>
private static IHtmlString RenderPartials(this HtmlHelper htmlHelper, ArchetypeModel archetypeModel, string partialPath, ViewDataDictionary viewDataDictionary)
{
var context = HttpContext.Current;
if (archetypeModel == null || context == null)
{
return new HtmlString("");
}
var sb = new StringBuilder();
var pathToPartials = "~/Views/Partials/Archetype/";
if (!string.IsNullOrEmpty(partialPath))
{
pathToPartials = partialPath;
}
foreach (var fieldsetModel in archetypeModel)
{
var partial = pathToPartials + fieldsetModel.Alias + ".cshtml";
if (System.IO.File.Exists(context.Server.MapPath(partial)))
{
sb.AppendLine(htmlHelper.Partial(partial, fieldsetModel, viewDataDictionary).ToString());
}
else
{
LogHelper.Info<ArchetypeModel>(string.Format("The partial for {0} could not be found. Please create a partial with that name or rename your alias.", context.Server.MapPath(partial)));
}
}
return new HtmlString(sb.ToString());
return htmlHelper._renderPartials(archetypeModel, partialPath, viewDataDictionary);
}
}
}
@@ -0,0 +1,10 @@
using System;
namespace Archetype.Models
{
public class ArchetypeConfigFileModel
{
public Guid Id { get; set; }
public bool CheckForUpdates { get; set; }
}
}
@@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Security;
using Archetype.TypeConverters;
using Newtonsoft.Json;
using Umbraco.Core;
using System;
namespace Archetype.Models
{
/// <summary>
/// Model that represents a fieldset stored as content JSON.
/// </summary>
[TypeConverter(typeof(ArchetypeFieldsetModelConverter))]
public class ArchetypeFieldsetModel
{
[JsonProperty("alias")]
@@ -23,6 +27,15 @@ namespace Archetype.Models
[JsonProperty("id")]
public Guid Id { get; set; }
[JsonProperty("releaseDate")]
public DateTime? ReleaseDate { get; set; }
[JsonProperty("expireDate")]
public DateTime? ExpireDate { get; set; }
[JsonProperty("allowedMemberGroups")]
public string AllowedMemberGroups { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ArchetypeFieldsetModel"/> class.
/// </summary>
@@ -53,7 +66,7 @@ namespace Archetype.Models
{
var property = GetProperty(propertyAlias);
if (IsEmptyProperty(property))
if (IsEmptyProperty(property))
{
return default(T);
}
@@ -77,7 +90,7 @@ namespace Archetype.Models
{
var property = GetProperty(propertyAlias);
if (IsEmptyProperty(property))
if (IsEmptyProperty(property))
{
return defaultValue;
}
@@ -90,7 +103,7 @@ namespace Archetype.Models
/// </summary>
/// <param name="property">The property.</param>
/// <returns></returns>
private bool IsEmptyProperty(ArchetypePropertyModel property)
private bool IsEmptyProperty(ArchetypePropertyModel property)
{
return (property == null || property.Value == null || string.IsNullOrEmpty(property.Value.ToString()));
}
@@ -129,6 +142,32 @@ namespace Archetype.Models
return Properties.FirstOrDefault(p => p.Alias.InvariantEquals(propertyAlias));
}
/// <summary>
/// Is this fieldset disabled, either explicitly or by other means?
/// </summary>
/// <returns>true if this fieldset is disabled, false otherwise</returns>
internal bool IsAvailable()
{
// explicitly disabled or implicitly disabled through publishing?
var disabled = Disabled
|| (ReleaseDate.HasValue && ReleaseDate > DateTime.UtcNow)
|| (ExpireDate.HasValue && DateTime.UtcNow > ExpireDate);
if (disabled)
{
// yes - the fieldset is not available
return false;
}
// limitation on member group access?
if (string.IsNullOrEmpty(AllowedMemberGroups))
{
// no - the fieldset is available
return true;
}
// maybe - the fieldset is available if the current member is a member of the configured member groups
var currentUserGroups = Roles.GetRolesForUser() ?? new string[0];
return currentUserGroups.ContainsAny(AllowedMemberGroups.Split(','));
}
#endregion
}
}
@@ -0,0 +1,134 @@
using System;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
namespace Archetype.Models
{
public class ArchetypeGlobalSettings
{
public bool CheckForUpdates { get; set; }
public Guid Id { get; set; }
public Guid ApiKey = _getApiKey();
private static ArchetypeGlobalSettings _instance;
private static string _pathToConfig = @"~/Config/Archetype.config.js";
private static readonly string _mappedPathToConfig = IOHelper.MapPath(_pathToConfig);
private static object _padLock = new object();
private ArchetypeGlobalSettings()
{
}
public static ArchetypeGlobalSettings Instance
{
get
{
if (_instance == null)
{
lock (_padLock)
{
if (_instance == null)
{
_instance = new ArchetypeGlobalSettings();
_loadSettingsFromConfigFile();
}
}
}
return _instance;
}
}
public void Save()
{
lock (_padLock)
{
//write to JSON
var configFileModel = new ArchetypeConfigFileModel
{
Id = _instance.Id,
CheckForUpdates = _instance.CheckForUpdates
};
var serializedJson = JsonConvert.SerializeObject(configFileModel, Formatting.Indented);
File.WriteAllText(_mappedPathToConfig, serializedJson);
}
}
private static void _loadSettingsFromConfigFile()
{
try
{
if (File.Exists(_mappedPathToConfig))
{
//load
var deserializedConfigFile = JsonConvert.DeserializeObject<ArchetypeConfigFileModel>(File.ReadAllText(_mappedPathToConfig));
if (deserializedConfigFile != null)
{
_instance.Id = deserializedConfigFile.Id;
_instance.CheckForUpdates = deserializedConfigFile.CheckForUpdates;
}
else
{
_createNewConfigFile("Config file model was null!");
}
}
else
{
_createNewConfigFile("Config file was missing!");
}
}
catch (Exception ex)
{
LogHelper.Error<ArchetypeGlobalSettings>(ex.Message, ex);
_createNewConfigFile("Exception!");
}
}
private static void _createNewConfigFile(string reason)
{
//write a new file with defaults
LogHelper.Info<ArchetypeGlobalSettings>(string.Format("Generating a new config file reason: {0}", reason));
_instance.Id = Guid.NewGuid();
_instance.CheckForUpdates = true;
_instance.Save();
}
private static Guid _getApiKey()
{
//this is just obfuscation and an attempt to keep out most but not the determined hacker
var array = new []
{
"RTA4MUZDRjA=",
"NzkzQS1BRDIw",
"OTI3QjFDNjkwQTYy",
"MjI0OQ=="
};
return new Guid(string.Format("{0}-{1}-{3}-{2}",
_decodeBase64(array[0]),
_decodeBase64(array[1]),
_decodeBase64(array[2]),
_decodeBase64(array[3])
));
}
private static string _decodeBase64(string input)
{
return Encoding.UTF8.GetString(Convert.FromBase64String(input));
}
}
}
@@ -1,7 +1,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Archetype.TypeConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -11,6 +13,7 @@ namespace Archetype.Models
/// Model that represents an entire Archetype.
/// </summary>
[JsonObject]
[TypeConverter(typeof(ArchetypeModelConverter))]
public class ArchetypeModel : IEnumerable<ArchetypeFieldsetModel>
{
[JsonProperty("fieldsets")]
@@ -32,7 +35,7 @@ namespace Archetype.Models
/// </returns>
public IEnumerator<ArchetypeFieldsetModel> GetEnumerator()
{
return this.Fieldsets.Where(f => f.Disabled == false).GetEnumerator();
return this.Fieldsets.Where(f => f.IsAvailable()).GetEnumerator();
}
//possibly obsolete?
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
@@ -25,18 +25,33 @@ namespace Archetype.Models
[JsonProperty("enableCollapsing")]
public bool EnableCollapsing { get; set; }
[JsonProperty("enableMultipleOpen")]
public bool EnableMultipleOpen { get; set; }
[JsonProperty("enableCloning")]
public bool EnableCloning { get; set; }
[JsonProperty("enableDisabling")]
public bool EnableDisabling { get; set; }
[JsonProperty("enablePublishing")]
public bool EnablePublishing { get; set; }
[JsonProperty("enableCrossDragging")]
public bool EnableCrossDragging { get; set; }
[JsonProperty("enableMemberGroups")]
public bool EnableMemberGroups { get; set; }
[JsonProperty("hideFieldsetControls")]
public bool HideFieldsetControls { get; set; }
[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; }
@@ -26,6 +26,9 @@ namespace Archetype.Models
[JsonProperty("label")]
public string Label { get; set; }
[JsonProperty("previewImage")]
public string PreviewImage { get; set; }
[JsonProperty("properties")]
public IEnumerable<ArchetypePreValueProperty> Properties { get; set; }
@@ -11,14 +11,17 @@ namespace Archetype.Models
{
private ArchetypeFieldsetModel _fieldset;
private IEnumerable<IPublishedContent> _parent;
private readonly Dictionary<string, IPublishedProperty> _properties;
public ArchetypePublishedContent(ArchetypeFieldsetModel fieldset)
public ArchetypePublishedContent(ArchetypeFieldsetModel fieldset, ArchetypePublishedContentSet parent = null)
{
if (fieldset == null)
throw new ArgumentNullException("fieldset");
_fieldset = fieldset;
_parent = parent ?? Enumerable.Empty<IPublishedContent>();
_properties = fieldset.Properties
.ToDictionary(
@@ -39,7 +42,7 @@ namespace Archetype.Models
public IEnumerable<IPublishedContent> ContentSet
{
get { return Enumerable.Empty<IPublishedContent>(); }
get { return _parent; }
}
public PublishedContentType ContentType
@@ -74,7 +77,7 @@ namespace Archetype.Models
public int GetIndex()
{
return default(int);
return _parent.IndexOf(this);
}
public IPublishedProperty GetProperty(string alias, bool recurse)
@@ -95,7 +98,7 @@ namespace Archetype.Models
public bool IsDraft
{
get { return _fieldset.Disabled; }
get { return _fieldset.IsAvailable() == false; }
}
public PublishedItemType ItemType
@@ -16,9 +16,12 @@ namespace Archetype.Models
this.ArchetypeModel = archetype;
var count = archetype.Fieldsets.Count();
_items = archetype.Fieldsets
.Where(x => x.Disabled == false)
.Select(x => new ArchetypePublishedContent(x));
.Where(x => x.IsAvailable())
.Select(x => new ArchetypePublishedContent(x, this))
.ToArray();
}
internal ArchetypeModel ArchetypeModel { get; private set; }
@@ -1,5 +1,6 @@
using System;
using Archetype.Extensions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
@@ -24,14 +25,22 @@ namespace Archetype.Models
_property = property;
_rawValue = property.Value;
_propertyType = property.CreateDummyPropertyType();
// #418 - need to wrap this in a try/catch to prevent orphaned properties from breaking everything
try
{
_propertyType = property.CreateDummyPropertyType();
if (_propertyType != null)
{
_sourceValue = new Lazy<object>(() => _propertyType.ConvertDataToSource(_rawValue, preview));
_objectValue = new Lazy<object>(() => _propertyType.ConvertSourceToObject(_sourceValue.Value, preview));
_xpathValue = new Lazy<object>(() => _propertyType.ConvertSourceToXPath(_sourceValue.Value, preview));
}
if (_propertyType != null)
{
_sourceValue = new Lazy<object>(() => _propertyType.ConvertDataToSource(_rawValue, preview));
_objectValue = new Lazy<object>(() => _propertyType.ConvertSourceToObject(_sourceValue.Value, preview));
_xpathValue = new Lazy<object>(() => _propertyType.ConvertSourceToXPath(_sourceValue.Value, preview));
}
}
catch(Exception ex)
{
LogHelper.Warn<ArchetypePublishedProperty>(string.Format("Could not create an IPublishedProperty for property: {0} - the error was: {1}", property.Alias, ex.Message));
}
}
internal ArchetypePropertyModel ArchetypeProperty
@@ -0,0 +1,11 @@
namespace Archetype.Models
{
public class ArchetypeUpdateNotification
{
public bool IsUpdateAvailable { get; set; }
public string Headline { get; set; }
public string Type { get; set; }
public string Message { get; set; }
public string Url { get; set; }
}
}
@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Archetype")]
[assembly: AssemblyDescription("Archetype's supporting code library for Umbraco")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Imulus")]
[assembly: AssemblyCompany("Kevin Giszewski LLC")]
[assembly: AssemblyProduct("Archetype")]
[assembly: AssemblyCopyright("MIT Licensed")]
[assembly: AssemblyTrademark("")]
@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("1.12.1")]
[assembly: AssemblyFileVersion("1.12.1")]
[assembly: AssemblyVersion("1.17.1")]
[assembly: AssemblyFileVersion("1.17.1")]
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Archetype.Extensions;
using Archetype.Models;
using ClientDependency.Core;
using Newtonsoft.Json;
using Umbraco.Core;
@@ -175,6 +176,10 @@ namespace Archetype.PropertyEditors
var uploadedFiles = editorValue.AdditionalData.ContainsKey("files") ? editorValue.AdditionalData["files"] as IEnumerable<ContentItemFile> : null;
foreach (var fieldset in archetype.Fieldsets)
{
// make sure the publishing dates are in UTC
fieldset.ReleaseDate = EnsureUtcDate(fieldset.ReleaseDate);
fieldset.ExpireDate = EnsureUtcDate(fieldset.ExpireDate);
// 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)
@@ -201,13 +206,28 @@ namespace Archetype.PropertyEditors
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();
var propertyFiles = propDef.EditorState.FileNames.Select(fileName =>
uploadedFiles.FirstOrDefault(u => u.FileName != null &&
// #384, #389 and #394 - look for "safe" file names (using the ToSafeFileName() extension)
// - for backwards compatibility we'll look for the raw filename as well as the "safe" file name
(u.FileName.Equals(fileName, StringComparison.OrdinalIgnoreCase) || u.FileName.Equals(fileName.ToSafeFileName(), StringComparison.OrdinalIgnoreCase))
)
).Where(f => f != null).ToList();
if(propertyFiles.Any())
{
additionalData["files"] = propertyFiles;
}
}
}
// #397 - pass along "cuid" and "puid" (part of the Umbraco 7.6 scheme)
if(editorValue.AdditionalData.ContainsKey("cuid"))
{
additionalData["cuid"] = editorValue.AdditionalData["cuid"];
}
if(editorValue.AdditionalData.ContainsKey("puid"))
{
additionalData["puid"] = editorValue.AdditionalData["puid"];
}
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
@@ -237,6 +257,20 @@ namespace Archetype.PropertyEditors
? new ArchetypePropertyEditor()
: (PropertyEditor) new TextboxPropertyEditor();
}
/// <summary>
/// Ensures that a datetime is in UTC
/// </summary>
/// <param name="dateTime">The datetime</param>
/// <returns>The datetime in UTC (or null if it's not set)</returns>
private DateTime? EnsureUtcDate(DateTime? dateTime)
{
if(dateTime.HasValue == false || dateTime.Value.Kind == DateTimeKind.Utc)
{
return dateTime;
}
return new DateTime(dateTime.Value.Ticks, DateTimeKind.Utc);
}
}
#endregion
@@ -0,0 +1,39 @@
using System;
using System.ComponentModel;
using System.Globalization;
using Archetype.Extensions;
using Archetype.Models;
using Umbraco.Core.Models;
namespace Archetype.TypeConverters
{
public class ArchetypeFieldsetModelConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(IPublishedContent) ||
destinationType == typeof(ArchetypePublishedContent))
{
return true;
}
if (destinationType == typeof(string))
{
// NOTE: The converter needs to return false here, otherwise `ArchetypeHelper.DeserializeJsonToArchetype` fails.
return false;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is ArchetypeFieldsetModel && (destinationType == typeof(IPublishedContent) || destinationType == typeof(ArchetypePublishedContent)))
{
return ((ArchetypeFieldsetModel)value).ToPublishedContent();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using Archetype.Extensions;
using Archetype.Models;
using Umbraco.Core.Models;
namespace Archetype.TypeConverters
{
public class ArchetypeModelConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(ArchetypePublishedContentSet) ||
destinationType == typeof(IEnumerable<IPublishedContent>))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is ArchetypeModel && (destinationType == typeof(ArchetypePublishedContentSet) || destinationType == typeof(IEnumerable<IPublishedContent>)))
{
return ((ArchetypeModel)value).ToPublishedContentSet();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
+32 -16
View File
@@ -1,4 +1,4 @@
angular.module("umbraco").controller("Imulus.ArchetypeConfigController", function ($scope, $http, assetsService, dialogService, archetypePropertyEditorResource) {
angular.module("umbraco").controller("Imulus.ArchetypeConfigController", function ($scope, $http, assetsService, dialogService, archetypePropertyEditorResource, archetypeGlobalConfigService, notificationsService) {
//$scope.model.value = "";
//console.log($scope.model.value);
@@ -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 + '], "group": null}';
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "maxFieldsets": null, "enableCollapsing": true, "enableCloning": false, "enableDisabling": true, "enableDeepDatatypeRequests": false, "fieldsets": [' + newFieldsetModel + '], "fieldsetGroups": []}');
var defaultFieldsetConfigModel = JSON.parse('{"showAdvancedOptions": false, "startWithAddButton": false, "hideFieldsetToolbar": false, "enableMultipleFieldsets": false, "hideFieldsetControls": false, "hidePropertyLabel": false, "maxFieldsets": null, "enableCollapsing": true, "enableMultipleOpen": true, "enableCloning": false, "enableDisabling": true, "enableDeepDatatypeRequests": false, "enablePublishing": false, "enableMemberGroups": false, "enableCrossDragging": false, "fieldsets": [' + newFieldsetModel + '], "fieldsetGroups": []}');
//ini the model
$scope.model.value = $scope.model.value || defaultFieldsetConfigModel;
@@ -16,6 +16,17 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
archetypePropertyEditorResource.getDllVersion().then(function(data){
$scope.dllVersion = data.dllVersion;
});
archetypeGlobalConfigService.checkForUpdates().then(function(data) {
if(data.isUpdateAvailable) {
notificationsService.add({
headline: data.headline,
type: data.type,
message: data.message,
url: data.url
});
}
});
//ini the render model
initConfigRenderModel();
@@ -47,6 +58,12 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
}
};
// added to track loaded fieldsets
$scope.loadedFieldsets = [];
$scope.isLoaded = function (fieldset) {
return $scope.loadedFieldsets.indexOf(fieldset) >= 0;
}
//function that determines how to manage expanding/collapsing fieldsets
$scope.focusFieldset = function(fieldset){
var iniState;
@@ -60,6 +77,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
if($scope.archetypeConfigRenderModel.fieldsets.length == 1 && fieldset.remove == false)
{
fieldset.collapse = false;
$scope.loadedFieldsets.push(fieldset);
return;
}
@@ -70,12 +88,14 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
else
{
fieldset.collapse = false;
$scope.loadedFieldsets.push(fieldset);
}
});
if(iniState)
{
fieldset.collapse = !iniState;
$scope.loadedFieldsets.push(fieldset);
}
}
@@ -123,27 +143,20 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
//watch for changes
$scope.$watch('archetypeConfigRenderModel', function (v) {
//console.log(v);
if (typeof v === 'string') {
$scope.archetypeConfigRenderModel = JSON.parse(v);
$scope.archetypeConfigRenderModel.toString = stringify;
}
});
$scope.autoPopulateAlias = function(s) {
var modelType = s.hasOwnProperty('fieldset') ? 'fieldset' : 'property';
var modelProperty = s[modelType];
if (!modelProperty.aliasIsDirty) {
$scope.autoPopulateAlias = function (modelProperty) {
if (modelProperty && !modelProperty.aliasIsDirty) {
modelProperty.alias = modelProperty.label.toUmbracoAlias();
}
}
$scope.markAliasDirty = function(s) {
var modelType = s.hasOwnProperty('fieldset') ? 'fieldset' : 'property';
var modelProperty = s[modelType];
if (!modelProperty.aliasIsDirty) {
$scope.markAliasDirty = function (modelProperty) {
if (modelProperty && !modelProperty.aliasIsDirty) {
modelProperty.aliasIsDirty = true;;
}
}
@@ -313,10 +326,13 @@ angular.module("umbraco").controller("Imulus.ArchetypeConfigController", functio
dialogService.open({
template: template,
show: true,
callback: function(data) {
$scope.archetypeConfigRenderModel = data;
callback: function (data) {
// replace the entire render model if it was changed (in developer options)
if (data.model && data.modelChanged) {
$scope.archetypeConfigRenderModel = data.model;
}
},
dialogData: $scope.archetypeConfigRenderModel
dialogData: { model: $scope.archetypeConfigRenderModel }
});
}
+4 -5
View File
@@ -1,17 +1,16 @@
angular.module('umbraco').controller('ArchetypeConfigOptionsController', function ($scope) {
$scope.model = angular.copy($scope.dialogData);
//handles a fieldset group add
$scope.addFieldsetGroup = function () {
$scope.model.fieldsetGroups.push({ name: "" });
$scope.dialogData.model.fieldsetGroups.push({ name: "" });
}
//handles a fieldset group removal
$scope.removeFieldsetGroup = function ($index) {
$scope.model.fieldsetGroups.splice($index, 1);
$scope.dialogData.model.fieldsetGroups.splice($index, 1);
}
$scope.apply = function(index) {
$scope.submit($scope.model);
$scope.submit($scope.dialogData);
}
});
@@ -0,0 +1,21 @@
angular.module('umbraco').controller('ArchetypeConfigGlobalOptionsController', function ($scope, archetypeGlobalConfigService) {
$scope.globalSettings = {};
$scope.confirmCheckNewVersionChange = function() {
archetypeGlobalConfigService.setCheckForUpdates($scope.globalSettings.checkForNewVersion);
}
function getGlobalSettings()
{
archetypeGlobalConfigService.globalSettings().then(function(data) {
$scope.globalSettings.checkForNewVersion = data.isCheckingForUpdates;
});
}
init();
function init()
{
getGlobalSettings();
}
});
+591 -64
View File
@@ -1,5 +1,10 @@
{{VERSION}}
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, $filter, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource) {
angular.module("umbraco").controller("Imulus.ArchetypeController", function ($scope, $http, $filter, $interpolate, assetsService, angularHelper, notificationsService, $timeout, fileManager, entityResource, archetypeService, archetypeLabelService, archetypeCacheService, archetypePropertyEditorResource, archetypeLocalizationService) {
// Variables.
var draggedParent;
var isCacheInitialized = false;
//$scope.model.value = "";
$scope.model.hideLabel = $scope.model.config.hideLabel == 1;
@@ -15,6 +20,8 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
// store the umbraco property alias to help generate unique IDs. Hopefully there's a better way to get this in the future :)
$scope.umbracoHostPropertyAlias = $scope.$parent.$parent.model.alias;
$scope.isDebuggingEnabled = Umbraco.Sys.ServerVariables.isDebuggingEnabled;
$scope.overlayMenu = {
show: false,
@@ -22,55 +29,262 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
};
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.fieldsetTitles = [];
$scope.getFieldsetTitle = function (fieldsetConfigModel, fieldsetIndex) {
return archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex);
}
if(!isCacheInitialized) {
return "";
}
// Ensure the collection of titles is large enough.
ensureEnoughTitles(fieldsetIndex + 1);
var title = $scope.fieldsetTitles[fieldsetIndex];
var draggedRteSettings;
var rteClass = ".umb-rte textarea";
// Return the title if it's already been loaded.
if (title.loaded) {
return title.value;
}
// Return early if the title is still loading.
if (title.loading) {
return;
}
// Start loading the title.
title.loading = true;
title.loaded = false;
title.value = null;
archetypeLabelService.getFieldsetTitle($scope, fieldsetConfigModel, fieldsetIndex).then(function(value) {
// Finished loading the title.
title.loaded = true;
title.loading = false;
title.value = value;
});
};
/**
* Ensure the collection of fieldset titles is large enough to accommodate the number of fieldsets.
* @param count The number of fieldsets.
*/
function ensureEnoughTitles(count) {
while ($scope.fieldsetTitles.length < count) {
$scope.fieldsetTitles.push({
loading: false,
loaded: false,
value: null
});
}
}
//sort config
$scope.sortableOptions = {
axis: 'y',
cursor: "move",
handle: ".handle",
tolerance: "pointer",
activate: function(ev, ui) {
// Variables.
var parentItem = ui.item.parent();
var thisElement = parentItem[0];
var targetElement = ev.target;
var targetItem = angular.element(targetElement);
// The source of the drag can always be dropped back onto.
if (targetElement === thisElement) {
return;
}
// Variables.
var sourceScope = ui.item.scope();
var targetScope = targetItem.scope();
var valid = canMove(sourceScope, targetScope);
// If the sortable can't be moved to the target Archetype, disable
// the target Archetype's sortable temporarily.
if (!valid) {
var targetSortable = getSortableWidgetInstance(targetItem);
targetSortable.disable();
parentItem.sortable("refresh");
archetypeService.rememberDisabledSortable(targetSortable);
}
},
start: function(ev, ui) {
draggedRteSettings = {};
$(rteClass, ui.item.parent()).each(function () {
var id = $(this).attr("id");
draggedRteSettings[id] = _.findWhere(tinyMCE.editors, { id: id }).settings;
tinymce.execCommand('mceRemoveEditor', false, id);
$(this).css("visibility", "hidden");
archetypeService.getEditors().addClass('archetypeDragging');
archetypeService.storeEditors(ui.item.parent());
$scope.$apply(function() {
draggedParent = ui.item.parent();
draggedParent.scope().doingSort = true;
});
},
update: function (ev, ui) {
// Variables.
var targetScope = ui.item.sortable.droptarget.scope();
var sourceScope = ui.item.scope();
var sameScope = sourceScope === targetScope;
var sourceIndex = ui.item.sortable.index;
// Special constraints for when moving between Archetypes.
// If sourceScope is populated, we are in the first of the two updates (when
// moving between lists, ui-sortable calls the update function twice).
if (sourceScope && !sameScope) {
// Variables.
var valid = canMove(sourceScope, targetScope);
// If update isn't allowed, cancel the drag operation.
if (!valid) {
ui.item.sortable.cancel();
return;
}
// Clear the validations for this item.
clearValidations(ui.item.parent());
clearValidations(ui.item.sortable.droptarget);
// Reset "isValid" on the properties and fieldsets.
var fieldsetGroups = [
$scope.model.value.fieldsets,
targetScope.model.value.fieldsets
];
_.each(fieldsetGroups, function(fieldsets) {
recurseProperties(function(property, fieldset) {
property.isValid = true;
fieldset.isValid = true;
}, fieldsets);
});
// Move the activated fieldset to the target Archetype.
var movedFieldset = $scope.model.value.fieldsets[sourceIndex];
var loadedIndex = $scope.loadedFieldsets.indexOf(movedFieldset);
if (loadedIndex >= 0) {
$scope.loadedFieldsets.splice(loadedIndex, 1);
if (targetScope.loadedFieldsets.indexOf(movedFieldset) < 0) {
targetScope.loadedFieldsets.push(movedFieldset);
}
}
}
// Set scope dirty.
$scope.setDirty();
},
stop: function (ev, ui) {
$(rteClass, ui.item.parent()).each(function () {
var id = $(this).attr("id");
draggedRteSettings[id] = draggedRteSettings[id] || _.findWhere(tinyMCE.editors, { id: id }).settings;
tinyMCE.execCommand("mceRemoveEditor", false, id);
tinyMCE.init(draggedRteSettings[id]);
});
// Done sorting.
draggedParent.scope().doingSort = false;
// Enable disabled sortables.
archetypeService.enableSortables();
// Restore rich text editors.
var parent = null;
var target = ui.item.sortable.droptarget;
if (target) {
parent = target.parent();
}
archetypeService.restoreEditors(parent);
archetypeService.getEditors().removeClass('archetypeDragging');
}
};
// Clears the Angular validations in an Archetype.
function clearValidations(el) {
var combined = $(".archetypeSortable", el).add(el);
combined.each(function(index, item) {
var $item = angular.element(item);
var cont = $item.controller("ngModel");
var err = cont.$error;
var keys = Object.keys(err);
for (var i = 0; i < keys.length; i++) {
cont.$setValidity(keys[i], true);
}
});
}
// Enable cross-archetype dragging?
if ($scope.model.config.enableCrossDragging) {
$scope.sortableOptions.connectWith = ".archetypeSortable:not(.invalid)";
}
// Checks if the specified model's properties match all of the properties in any of
// the specified fieldsets, while also checking if the fieldset aliases match.
// This is an indicator of the compatibility of a fieldset model with a collection
// of fieldset configurations.
function modelMatchesAnyFieldset(model, fieldsets) {
// Loop through fieldsets to find a match.
for (var i = 0; i < fieldsets.length; i++) {
var fieldset = fieldsets[i];
// Confirm that this configured fielset contains exactly
// the same properties as those that were supplied.
var valid =
// Does the alias match?
model.alias === fieldset.alias &&
// Does this fieldset have all the properties?
arePropertiesSubset(model.properties, fieldset.properties) &&
// Does the property array have all the fieldset properties?
arePropertiesSubset(fieldset.properties, model.properties);
// Match found?
if (valid) {
return true;
}
}
// No match found.
return false;
}
// Checks if the specified array of fieldsets contains the specified fieldset.
function arrayContainsFieldset(fieldset, fieldsets) {
for (var i = 0; i < fieldsets.length; i++) {
if (fieldsets[i] === fieldset) {
return true;
}
}
return false;
}
// Confirms that an array of properties is a subset of another array of properties.
function arePropertiesSubset(subset, superset) {
// Loop through the subset of properties.
for (var j = 0; j < subset.length; j++) {
var subProperty = subset[j];
var matchedProp = false;
// Loop through the superset to find a matching property from the subset.
for (var k = 0; k < superset.length; k++) {
var superProperty = superset[k];
if (superProperty.alias === subProperty.alias &&
superProperty.dataTypeGuid === subProperty.dataTypeGuid) {
matchedProp = true;
break;
}
}
// If no matching property could be found, the array is not a subset.
if (!matchedProp) {
return false;
}
}
// The array is a subset.
return true;
}
//handles a fieldset add
$scope.openFieldsetPicker = function ($index, event) {
if ($scope.canAdd() == false) {
@@ -84,7 +298,8 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
alias: fieldset.alias,
label: fieldset.label,
icon: (fieldset.icon || "icon-document-dashed-line"), // default icon if none is chosen
group: fieldset.group ? fieldset.group.name : null
group: fieldset.group ? fieldset.group.name : null,
previewImage: fieldset.previewImage
});
});
// sanity check
@@ -124,13 +339,22 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
$scope.closeFieldsetPicker = function () {
$scope.overlayMenu.show = false;
$scope.overlayMenu.fieldsetPreview = null;
};
$scope.pickFieldset = function (fieldsetAlias, $index) {
$scope.closeFieldsetPicker();
$scope.addRow(fieldsetAlias, $index);
};
$scope.openFieldsetPreview = function (fieldset) {
$scope.overlayMenu.fieldsetPreview = fieldset;
}
$scope.closeFieldsetPreview = function () {
$scope.overlayMenu.fieldsetPreview = null;
}
$scope.addRow = function (fieldsetAlias, $index) {
if ($scope.canAdd()) {
if ($scope.model.config.fieldsets) {
@@ -146,13 +370,21 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
}
}
addCustomPropertiesToFieldset(newFieldset);
$scope.setDirty();
$scope.$broadcast("archetypeAddFieldset", {index: $index, visible: countVisible()});
newFieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
// If the fieldset is not collapsed, it should be instantly loaded.
if (!newFieldset.collapse) {
$scope.loadedFieldsets.push(newFieldset);
}
$scope.focusFieldset(newFieldset);
$scope.handleMandatoryValidation();
}
}
@@ -162,6 +394,7 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
$scope.setDirty();
$scope.model.value.fieldsets.splice($index, 1);
$scope.$broadcast("archetypeRemoveFieldset", {index: $index});
$scope.handleMandatoryValidation();
}
}
}
@@ -172,11 +405,24 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
if(newFieldset) {
// Regenerate the temporary ID on each nested fieldset.
// This is done because no two fieldsets should have the same
// temporary ID.
recurseProperties(function(property) {
archetypeService.ensureTemporaryId(property, true);
}, [newFieldset]);
$scope.model.value.fieldsets.splice($index + 1, 0, newFieldset);
$scope.setDirty();
newFieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
// If the fieldset is not collapsed, it should be instantly loaded.
if (!newFieldset.collapse) {
$scope.loadedFieldsets.push(newFieldset);
}
$scope.focusFieldset(newFieldset);
}
}
@@ -186,24 +432,27 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
fieldset.disabled = !fieldset.disabled;
// explicitly set the form as dirty when manipulating the enabled/disabled state of a fieldset
$scope.setDirty();
$scope.handleMandatoryValidation();
}
//helpers for determining if a user can do something
$scope.canAdd = function () {
if ($scope.model.config.maxFieldsets)
{
return countVisible() < $scope.model.config.maxFieldsets;
var visibleCount = countVisible();
var maxFieldsets = $scope.model.config.maxFieldsets;
return visibleCount < maxFieldsets;
}
return true;
}
};
//helper that returns if an item can be removed
$scope.canRemove = function () {
return countVisible() > 1
|| ($scope.model.config.maxFieldsets == 1 && $scope.model.config.fieldsets.length > 1)
|| $scope.model.config.startWithAddButton;
}
};
$scope.canClone = function () {
@@ -222,8 +471,16 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
//helper that returns if an item can be sorted
$scope.canSort = function ()
{
return countVisible() > 1;
}
// Sorting can occur if there are multiple fieldsets, or if there is only one
// fieldset that can be removed (in which case it can be sorted into an entirely
// different Archetype).
return countVisible() > 1 || $scope.canRemove();
};
//helper that returns if an item is the last and it's being sorted.
$scope.sortingLastItem = function() {
return $scope.doingSort && $scope.model.value.fieldsets.length <= 1;
};
//helper that returns if an item can be disabled
$scope.canDisable = function () {
@@ -232,15 +489,110 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
//helpers for determining if the add button should be shown
$scope.showAddButton = function () {
var visible = countVisible();
return (visible === 0 && $scope.model.config.startWithAddButton)
|| (visible > 0 && $scope.canAdd());
}
//helper for determining if no content is available yet
$scope.showEmptyContentHint = function () {
return $scope.model.config.startWithAddButton
&& countVisible() === 0;
///&& $scope.model.config.fieldsets.length == 1;
}
//helper that returns if an item can use publishing
$scope.canPublish = function () {
return $scope.model.config.enablePublishing;
}
$scope.canUseMemberGroups = function() {
return $scope.model.config.enableMemberGroups;
}
//helper that returns if the "misc fieldset configuration" section should be visible
$scope.canConfigure = function () {
// currently the "misc fieldset configuration" section contains the publishing and the member groups setup
return $scope.canPublish() || $scope.canUseMemberGroups();
}
$scope.showDisableIcon = function (fieldset) {
if ($scope.canDisable() == false) {
return false;
}
// disabled state takes precedence over publishing
if (fieldset.disabled) {
return true;
}
return $scope.isDisabledByPublishing(fieldset) == false;
}
$scope.showPublishingIcon = function (fieldset) {
if ($scope.canPublish() == false) {
return false;
}
if ($scope.canDisable()) {
// disabled state takes precedence over publishing
if (fieldset.disabled) {
return false;
}
return $scope.isDisabledByPublishing(fieldset);
}
return true;
}
$scope.isDisabledByPublishing = function(fieldset) {
if ($scope.canPublish() === false) {
return false;
}
// NOTE: all comparison is done in local datetime
// - that's fine because the selected local datetimes will be converted to UTC datetimes when submitted
if (fieldset.expireDateModel && fieldset.expireDateModel.value && (moment() > moment(fieldset.expireDateModel.value))) {
// an expired release affects the fieldset
return true;
}
if (fieldset.releaseDateModel && fieldset.releaseDateModel.value && (moment(fieldset.releaseDateModel.value) > moment())) {
// a pending release affects the fieldset
return true;
}
return false;
}
$scope.isDisabled = function(fieldset) {
if (fieldset.disabled) {
return true;
}
return $scope.isDisabledByPublishing(fieldset);
}
$scope.numberOfEnabledFieldsets = function () {
if (!$scope.model.value.fieldsets) {
return 0;
}
return _.filter($scope.model.value.fieldsets, function (f) {
return $scope.isDisabled(f) == false;
}).length;
}
//helper, ini the render model from the server (model.value)
function init() {
$scope.model.value = removeNulls($scope.model.value);
addDefaultProperties($scope.model.value.fieldsets);
archetypeCacheService.initialize().then(function() {
isCacheInitialized = true;
});
$timeout(function () {
$scope.handleMandatoryValidation();
}, 50);
// localize the message for minimum fieldsets validation errors
archetypeLocalizationService.localize("minFieldsetsMessage").then(function (value) {
value = value || "You must add minimum {{minFieldsets}} items";
var exp = $interpolate(value);
$scope.minFieldsetsMessage = exp({ minFieldsets: $scope.model.config.minFieldsets });
});
}
function addDefaultProperties(fieldsets)
@@ -252,6 +604,36 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
});
}
function addCustomProperties(fieldsets) {
// make sure we have loaded moment.js before using it
assetsService.loadJs("lib/moment/moment-with-locales.js").then(function() {
_.each(fieldsets, function(fieldset) {
addCustomPropertiesToFieldset(fieldset);
});
});
}
function addCustomPropertiesToFieldset(fieldset) {
// create models for publish configuration (utilizing the built-in datepicker data type)
// NOTE: all datetimes must be converted from UTC to local
fieldset.releaseDateModel = {
alias: _.uniqueId("archetypeReleaseDate_"),
view: "datepicker",
value: fromUtc(fieldset.releaseDate)
};
fieldset.expireDateModel = {
alias: _.uniqueId("archetypeExpireDate_"),
view: "datepicker",
value: fromUtc(fieldset.expireDate)
};
// create model for allowed member groups
fieldset.allowedMemberGroupsModel = {
alias: _.uniqueId("archetypeAllowedMemberGroups_"),
view: "membergrouppicker",
value: fieldset.allowedMemberGroups
};
}
//helper to get the correct fieldset from config
$scope.getConfigFieldsetByAlias = function(alias) {
return _.find($scope.model.config.fieldsets, function(fieldset){
@@ -271,9 +653,15 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
{
if(typeof fieldset.collapse === "undefined")
{
fieldset.collapse = true;
fieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
}
return fieldset.collapse;
};
// added to track loaded fieldsets
$scope.loadedFieldsets = [];
$scope.isLoaded = function (fieldset) {
return $scope.loadedFieldsets.indexOf(fieldset) >= 0;
}
//helper for expanding/collapsing fieldsets
@@ -284,32 +672,43 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
return;
}
var iniState;
if(fieldset)
// collapse all other fieldsets if "multiple open fieldsets" is not enabled
if(!$scope.model.config.enableMultipleOpen)
{
iniState = fieldset.collapse;
_.each($scope.model.value.fieldsets, function (f) {
if(f != fieldset)
{
f.collapse = true;
}
});
}
_.each($scope.model.value.fieldsets, function(fieldset){
fieldset.collapse = true;
});
if(!fieldset && $scope.model.value.fieldsets.length == 1)
{
$scope.model.value.fieldsets[0].collapse = false;
$scope.loadedFieldsets.push($scope.model.value.fieldsets[0]);
return;
}
if(iniState && fieldset)
if(fieldset)
{
fieldset.collapse = !iniState;
fieldset.collapse = !fieldset.collapse;
if($scope.loadedFieldsets.indexOf(fieldset) < 0)
{
$scope.loadedFieldsets.push(fieldset);
}
}
}
//ini the fieldset expand/collapse
$scope.focusFieldset();
// Fieldsets which cannot be collapsed should start expanded.
_.each($scope.model.value.fieldsets, function(fieldset) {
fieldset.collapse = $scope.model.config.enableCollapsing;
});
$scope.loadedFieldsets = _.where($scope.model.value.fieldsets, { collapse: false });
//developerMode helpers
$scope.model.value.toString = stringify;
@@ -343,6 +742,14 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
fileManager.setFiles($scope.model.alias, archetypeFiles);
}
// Deep watch for changes.
$scope.$watch('model.value', function () {
// Empty titles. If the value has changed, the titles may have changed.
$scope.fieldsetTitles = [];
}, true);
//watch for changes
$scope.$watch('model.value', function (v) {
if ($scope.model.config.developerMode) {
@@ -359,6 +766,15 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
// reset submit watcher counter on save
$scope.activeSubmitWatcher = 0;
// init loaded fieldsets tracking
_.each($scope.model.value.fieldsets, function (fieldset) {
fieldset.collapse = $scope.model.config.enableCollapsing ? true : false;
});
$scope.loadedFieldsets = _.where($scope.model.value.fieldsets, { collapse: false });
// create properties needed for the backoffice to work (data that is not serialized to DB)
addCustomProperties($scope.model.value.fieldsets);
});
//helper to count what is visible
@@ -419,24 +835,21 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
//helper to lookup validity when given a fieldset
$scope.getFieldsetValidity = function (fieldset) {
if (fieldset.isValid == false) {
return false;
}
// 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) {
if ($scope.getFieldsetValidity(inner) == false) {
nestedFieldsetsValid = false;
}
});
// Variables.
var valid = true;
// Recursive validation of nested fieldsets.
recurseFieldsets(function(item) {
if (item.isValid === false) {
valid = false;
}
});
}, [fieldset]);
return nestedFieldsetsValid;
}
// Were all the nested fieldsets valid?
return valid;
};
// helper to force the current form into the dirty state
$scope.setDirty = function () {
@@ -445,6 +858,13 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
}
}
$scope.minFieldsetsFulfilled = function () {
if (!$scope.model.config.minFieldsets) {
return true;
}
return $scope.numberOfEnabledFieldsets() >= $scope.model.config.minFieldsets;
}
//custom js
if ($scope.model.config.customJsPath) {
assetsService.loadJs($scope.model.config.customJsPath);
@@ -471,4 +891,111 @@ angular.module("umbraco").controller("Imulus.ArchetypeController", function ($sc
$scope.submitWatcherOnSubmit = function (args) {
$scope.$broadcast("archetypeFormSubmitting", args);
}
// we'll use our own "archetypeFormSubmitting" event to save custom properties, as at least some
// of the editors store their values back to the model on the core "formSubmitting" event
$scope.$on("archetypeFormSubmitting", function (ev, args) {
_.each($scope.model.value.fieldsets, function (fieldset) {
// extract the publish configuration from the fieldsets (and convert local datetimes to UTC)
fieldset.releaseDate = toUtc(fieldset.releaseDateModel.value);
fieldset.expireDate = toUtc(fieldset.expireDateModel.value);
// extract the allowed member groups
fieldset.allowedMemberGroups = fieldset.allowedMemberGroupsModel.value;
});
});
// handle mandatory validation of the entire Archetype
// - no fieldsets = not valid
$scope.handleMandatoryValidation = function() {
var valid = true;
if ($scope.model.validation && $scope.model.validation.mandatory) {
valid = $scope.numberOfEnabledFieldsets() > 0;
}
$scope.model.mandatoryValidation = valid ? "valid" : null;
}
function toUtc(date) {
if (!date) {
return null;
}
return moment(date, "YYYY-MM-DD HH:mm:ss").utc().toDate();
}
function fromUtc(date) {
if (!date) {
return null;
}
return moment(moment.utc(date).toDate()).format("YYYY-MM-DD HH:mm:ss")
}
// Serializes and deserializes an item to return a snapshot of that item (e.g., so it is not
// changed before being inspected). Useful when troubleshooting.
// Modified from: http://stackoverflow.com/a/11616993/2052963
function jsonSnapshot(item) {
var cache = [];
var stringItem = JSON.stringify(item, function(key, value) {
if (typeof value === "object" && value !== null) {
if (cache.indexOf(value) !== -1) {
return "[Removed Circular Reference Item]";
}
cache.push(value);
}
return value;
});
return JSON.parse(stringItem);
}
// Recursively processes each Archetype fieldset.
function recurseFieldsets(fn, fieldsets) {
if (!fieldsets || !fieldsets.length) {
return;
}
_.each(fieldsets, function(fieldset) {
fn(fieldset);
_.each(fieldset.properties, function (property) {
if (property != null && property.value != null && property.propertyEditorAlias === "Imulus.Archetype") {
recurseFieldsets(fn, property.value.fieldsets);
}
});
});
}
// Recursively processes each Archetype fieldset property.
function recurseProperties(fn, fieldsets) {
recurseFieldsets(function(fieldset) {
_.each(fieldset.properties, function (property) {
fn(property, fieldset);
});
}, fieldsets);
}
// Indicates whether or not the fieldset can be moved between the source and target scope.
// The source scope is the scope of the fieldset being dragged.
// The target scope is the scope of the Archetype to drop into.
function canMove(sourceScope, targetScope) {
var targetFieldsetConfigs = targetScope.model.config.fieldsets;
var targetFieldsets = targetScope.model.value.fieldsets;
var sourceFieldset = sourceScope.fieldset;
var sameArchetype = arrayContainsFieldset(sourceFieldset, targetFieldsets);
var model = sourceScope.fieldsetConfigModel;
var canRemove = sourceScope.canRemove();
var canAdd = targetScope.canAdd();
var valid = sameArchetype || (canRemove && canAdd);
valid = valid && modelMatchesAnyFieldset(model, targetFieldsetConfigs);
return valid;
}
// This is an alternative to: element.sortable("instance")
// Workaround for this issue: https://github.com/imulus/Archetype/pull/356#issuecomment-218527910
// Snagged from this pull request: https://github.com/angular-ui/ui-sortable/pull/319
// More technical details here: https://github.com/angular-ui/ui-sortable/issues/316
function getSortableWidgetInstance(element) {
// this is a fix to support jquery-ui prior to v1.11.x
// otherwise we should be using `element.sortable('instance')`
var data = element.data('ui-sortable');
if (data && typeof data === 'object' && data.widgetFullName === 'ui-sortable') {
return data;
}
return null;
}
});
+1 -1
View File
@@ -1,7 +1,7 @@
angular.module("umbraco.directives").directive('archetypeCustomView', function ($compile, $http) {
var linker = function (scope, element, attrs) {
var view = "/App_plugins/Archetype/views/archetype.default.html";
var view = "../App_plugins/Archetype/views/archetype.default.html";
if(scope.model.config.customViewPath) {
view = scope.model.config.customViewPath;
}
+24 -17
View File
@@ -1,4 +1,4 @@
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService, archetypeCacheService) {
angular.module("umbraco.directives").directive('archetypeProperty', function ($compile, $http, archetypePropertyEditorResource, umbPropEditorHelper, $timeout, $rootScope, $q, fileManager, editorState, archetypeService) {
var linker = function (scope, element, attrs, ngModelCtrl) {
var configFieldsetModel = archetypeService.getFieldsetByAlias(scope.archetypeConfig.fieldsets, scope.fieldset.alias);
@@ -25,9 +25,6 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
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);
@@ -65,15 +62,22 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
if (!scope.renderModelPropertyIndex)
{
archetypeService.getFieldset(scope).properties.push(JSON.parse('{"alias": "' + alias + '", "value": "' + defaultValue + '"}'));
var propertyValue = { alias: alias, value: defaultValue };
archetypeService.getFieldset(scope).properties.push(propertyValue);
scope.renderModelPropertyIndex = archetypeService.getPropertyIndexByAlias(archetypeService.getFieldset(scope).properties, alias);
}
scope.renderModel = {};
scope.model.value = archetypeService.getFieldsetProperty(scope).value;
//init the property editor state
archetypeService.getFieldsetProperty(scope).editorState = {};
// init the property editor state (while ensuring the temporary ID is retained
// from any prior initializations).
var fieldsetProperty = archetypeService.getFieldsetProperty(scope);
var oldState = fieldsetProperty.editorState;
archetypeService.ensureTemporaryId(fieldsetProperty);
if (oldState) {
fieldsetProperty.editorState.temporaryId = oldState.temporaryId;
}
//set the config from the prevalues
scope.model.config = config;
@@ -93,9 +97,11 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
}
}
//upload datatype hack
if(view.indexOf('fileupload.html') != -1) {
//hacks for various built-in datatyps including upload, colorpicker and tags
if (!scope.propertyForm) {
scope.propertyForm = scope.form;
}
if (!scope.model.validation) {
scope.model.validation = {};
scope.model.validation.mandatory = 0;
}
@@ -115,16 +121,17 @@ angular.module("umbraco.directives").directive('archetypeProperty', function ($c
});
scope.$on('archetypeFormSubmitting', function (ev, args) {
if(args.action !== 'save') {
// validate all fieldset properties
_.each(scope.fieldset.properties, function (property) {
archetypeService.validateProperty(scope.fieldset, property, configFieldsetModel);
});
// #385 - revert the changes made in #311 to avoid publishing invalid fieldsets (leaving the code from #311 here, in case we figure out how to re-introduce "save as draft")
// if(args.action !== 'save') {
// validate all fieldset properties
_.each(scope.fieldset.properties, function (property) {
archetypeService.validateProperty(scope.fieldset, property, configFieldsetModel);
});
var validationKey = "validation-f" + scope.fieldsetIndex;
var validationKey = "validation-f" + scope.fieldsetIndex;
ngModelCtrl.$setValidity(validationKey, scope.fieldset.isValid);
}
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);
+3 -3
View File
@@ -1,9 +1,9 @@
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) {
var id = scope.loadCallback ? scope.loadCallback() : 0;
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(args);
@@ -22,4 +22,4 @@ angular.module("umbraco.directives").directive('archetypeSubmitWatcher', functio
activeSubmitWatcher: '='
}
}
});
});
+49 -68
View File
@@ -1,70 +1,51 @@
var ArchetypeSampleLabelTemplates = (function() {
//create a namespace (optional)
var ArchetypeSampleLabelHelpers = {};
//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);
}
//create a function
//you will add it to your label template field as `{{ArchetypeSampleLabelHelpers.testPromise(someArchetypePropertyAlias)}}`
ArchetypeSampleLabelHelpers.testPromise = function(value) {
//you can inject services
return function ($timeout, archetypeCacheService) {
//best to return a promise
//NOTE: $timeout returns a promise
return $timeout(function () {
return "As Promised: " + value;
}, 1000);
}
})();
}
ArchetypeSampleLabelHelpers.testEntityPromise = function(value, scope, args) {
//hey look, args!
//{{ArchetypeSampleLabelHelpers.testEntityPromise(someArchetypePropertyAlias, {foo: 1})}}
console.log(args);
return function ($q, entityResource) {
var deferred = $q.defer();
entityResource.getById(args.foo, 'document').then(function(entity) {
console.log("Hello from testEntityPromise");
console.log(entity);
deferred.resolve(entity.name);
});
return deferred.promise;
}
}
ArchetypeSampleLabelHelpers.testEntityPromise2 = function(value, scope, args) {
//hey look, args but we're also using the built-in archetypeCacheService
//{{ArchetypeSampleLabelHelpers.testEntityPromise(someArchetypePropertyAlias, {foo: 1234})}}
console.log(args);
return function ($q, archetypeCacheService) {
var deferred = $q.defer();
archetypeCacheService.getEntityById(args.foo, 'document').then(function(entity) {
console.log("Hello from testEntityPromise2");
console.log(entity);
deferred.resolve(entity.name);
});
return deferred.promise;
}
}
+15 -1
View File
@@ -44,5 +44,19 @@
"fieldsetGroups":"Fieldset-grupper",
"fieldsetGroupsDescription":"Hvis du har mange fieldsets, skal du måske overveje at gruppere dem i fieldset-vælgeren. Når du først har defineret dine grupper her, vil en gruppe-vælger dukke op i fieldset-editoren, og du kan derefter vælge grupper for alle dine fieldsets.",
"fieldsetGroupName":"Navn",
"addFieldsetGroup":"Tilføj gruppe"
"addFieldsetGroup":"Tilføj gruppe",
"enablePublishing": "Aktivér fieldset-publicering?",
"enablePublishingDescription": "Tillad automatisk udgivelse og udløb for fieldsets",
"publish": "Publicering",
"publishHelpText": "Konfigurér udgivelses- og udløbsdato for dette element",
"publishReleaseDate": "Udgivelsesdato",
"publishExpireDate": "Udløbsdato",
"settings": "Indstillinger",
"enableMemberGroups": "Aktivér medlems-grupper",
"enableMemerGroupsDescription": "Tillad at fieldsets kun vises for specifikke medlems-grupper",
"allowedMemberGroups": "Tilladte medlems-grupper",
"allowedMemberGroupsHelpText": "Vælg de medlems-grupper, der skal kunne se dette element. Hvis der ikke er valgt nogen, kan alle se elementet.",
"previewFieldsetOpen": "(se eksempel)",
"previewFieldsetHeader": "Eksempel: ",
"previewFieldsetClose": "(luk eksempel)"
}
+15 -1
View File
@@ -44,5 +44,19 @@
"fieldsetGroups":"Fieldset-grupper",
"fieldsetGroupsDescription":"Hvis du har mange fieldsets, skal du måske overveje at gruppere dem i fieldset-vælgeren. Når du først har defineret dine grupper her, vil en gruppe-vælger dukke op i fieldset-editoren, og du kan derefter vælge grupper for alle dine fieldsets.",
"fieldsetGroupName":"Navn",
"addFieldsetGroup":"Tilføj gruppe"
"addFieldsetGroup":"Tilføj gruppe",
"enablePublishing": "Aktivér fieldset-publicering?",
"enablePublishingDescription": "Tillad automatisk udgivelse og udløb for fieldsets",
"publish": "Publicering",
"publishHelpText": "Konfigurér udgivelses- og udløbsdato for dette element",
"publishReleaseDate": "Udgivelsesdato",
"publishExpireDate": "Udløbsdato",
"settings": "Indstillinger",
"enableMemberGroups": "Aktivér medlems-grupper",
"enableMemerGroupsDescription": "Tillad at fieldsets kun vises for specifikke medlems-grupper",
"allowedMemberGroups": "Tilladte medlems-grupper",
"allowedMemberGroupsHelpText": "Vælg de medlems-grupper, der skal kunne se dette element. Hvis der ikke er valgt nogen, kan alle se elementet.",
"previewFieldsetOpen": "(se eksempel)",
"previewFieldsetHeader": "Eksempel: ",
"previewFieldsetClose": "(luk eksempel)"
}
+4 -2
View File
@@ -11,7 +11,7 @@
"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.",
"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",
@@ -23,7 +23,7 @@
"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.",
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
@@ -41,6 +41,8 @@
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning.",
"enableCrossDragging":"Enable Cross-Archetype Dragging?",
"enableCrossDraggingDescription":"Allows fieldsets to be dragged into other Archetypes.",
"fieldsetGroups":"Fieldset groups",
"fieldsetGroupsDescription":"If you have a lot of fieldsets to choose from, you may want to consider grouping them in the fieldset picker. Once you have created your groups here, a group picker will be displayed in the fieldset editor and you can assign your fieldsets to their respective groups.",
"fieldsetGroupName":"Name",
+4 -2
View File
@@ -11,7 +11,7 @@
"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.",
"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",
@@ -23,7 +23,7 @@
"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.",
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
@@ -41,6 +41,8 @@
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning.",
"enableCrossDragging":"Enable Cross-Archetype Dragging?",
"enableCrossDraggingDescription":"Allows fieldsets to be dragged into other Archetypes.",
"fieldsetGroups":"Fieldset groups",
"fieldsetGroupsDescription":"If you have a lot of fieldsets to choose from, you may want to consider grouping them in the fieldset picker. Once you have created your groups here, a group picker will be displayed in the fieldset editor and you can assign your fieldsets to their respective groups.",
"fieldsetGroupName":"Name",
+4 -2
View File
@@ -11,7 +11,7 @@
"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.",
"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",
@@ -23,7 +23,7 @@
"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.",
"configModelDescription": "Be careful editing the text below, it controls the schema for this Archetype.",
"helpText": "Help Text",
"defaultValue": "Default Value",
"dataType": "DataType",
@@ -41,6 +41,8 @@
"overrideDefaultConverter":"Override Default Property Value Converter?",
"enableCloning":"Enable Cloning?",
"enableCloningDescription":"Enable Fieldset Cloning.",
"enableCrossDragging":"Enable Cross-Archetype Dragging?",
"enableCrossDraggingDescription":"Allows fieldsets to be dragged into other Archetypes.",
"fieldsetGroups":"Fieldset groups",
"fieldsetGroupsDescription":"If you have a lot of fieldsets to choose from, you may want to consider grouping them in the fieldset picker. Once you have created your groups here, a group picker will be displayed in the fieldset editor and you can assign your fieldsets to their respective groups.",
"fieldsetGroupName":"Name",
+308 -70
View File
@@ -33,29 +33,26 @@
margin-left: 0;
}
.icon {
color: #ddd;
padding: 2px;
font-size: 16px;
&:hover {
color: #333;
}
&.icon-delete:hover {
color: #b94a48;
}
}
.fieldsetIcon {
float: left;
padding: 0 4px 0 0;
color: #333;
padding: 0 10px 0 0;
vertical-align: text-bottom;
}
.caret {
margin: 8px 1px 0 2px;
&.caret-right {
border-bottom: 4px solid transparent;
border-top: 4px solid transparent;
border-left: 4px solid #ddd;
content: "";
margin-top: 6px;
}
}
fieldset {
border-bottom: 1px dashed #dddddd;
padding: 0;
margin-bottom: 5px;
clear: both;
display: inline-block;
width: 100%;
@@ -76,15 +73,28 @@
}
}
.publishOptions {
.publishDate {
display: inline-block;
vertical-align: top;
margin-right: 20px;
label {
padding: 0 !important;
margin: 0 !important;
}
}
}
}
.archetypeFieldsetLabel {
position: relative;
width: 100%;
min-height: 42px;
background: white;
.label-sub {
padding: 8px 0 8px 0;
padding: 18px 0;
display: inline-block;
min-height: 20px; /* this makes the header clickable when there's no icon and no text */
&.module-label {
@@ -94,9 +104,9 @@
cursor: pointer;
label {
span {
text-decoration: underline;
}
// span {
// text-decoration: underline;
// }
&:hover {
cursor: pointer;
}
@@ -117,7 +127,7 @@
}
span {
font-weight: bold;
// font-weight: bold;
&.menu-label { font-weight: normal; }
}
@@ -127,48 +137,105 @@
}
.caret {
margin: 8px 1px 0 2px;
position: absolute;
&.caret-right {
border-bottom: 4px solid transparent;
border-top: 4px solid transparent;
border-left: 4px solid #ddd;
content: "";
margin-top: 6px;
}
}
label {
margin-bottom: 0;
margin-left: 18px;
white-space: nowrap;
padding: 0;
width: ~"calc(100% - 144px)";
position: absolute;
display: block;
span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
max-height: 40px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
}
&.dimmed {
i, span {
color: #d9d9d9 !important;
}
}
&.dimmed {
label {
color: #d9d9d9 !important;
}
}
.archetypeEditorControls {
float: none;
position: absolute;
right: 15px;
right: 0;
top: 0;
height: 100%;
padding: 0;
display: flex;
align-items: center;
opacity: 0;
transition: opacity .15s ease-in-out;
-moz-transition: opacity .15s ease-in-out;
-webkit-transition: opacity .15s ease-in-out;
background: white;
&:before {
content: ' ';
position: absolute;
display: block;
left: -40px;
width: 40px;
top: 0;
bottom: 0;
background: -webkit-linear-gradient(90deg, rgba(255,255,255,0), white);
background: -moz-linear-gradient(90deg, rgba(255,255,255,0), white);
background: linear-gradient(90deg, rgba(255,255,255,0), white);
}
.icon {
display: inline-block;
height: 28px;
width: 28px;
line-height: 28px;
border-radius: 14px;
border: 1px solid #d6d6d6;
color: #5f5f5f;
background: white;
font-size: 16px;
text-align: center;
margin-left: 8px;
&:hover {
background: #f3f3f5;
}
&.icon-trash:hover {
background: #fe5b57;
border-color: #fe5b57;
color: white;
}
&.icon-disabled {
cursor: default;
&:hover {
color: #ddd;
background: white;
}
}
&.icon-active {
color: #bbb;
&:hover {
color: white;
}
}
}
}
&:hover {
&:hover .archetypeEditorControls {
opacity: 1;
}
}
&.is-open > .archetypeFieldsetLabel .archetypeEditorControls {
opacity: 1;
}
.archetypePropertyError {
margin-bottom: 5px;
padding-top: 3px;
@@ -186,9 +253,24 @@
.archetypeCollapser {
clear: both;
height: 100%;
padding: 12px 0 0 20px;
background-color: #fff;
border-radius: 0 0 0 5px;
padding: 24px 20px 0 20px;
background-color: #fafafa;
border-top: 1px dashed #e0e0e0;
line-height: 20px;
.archetypeFieldsetLabel {
background: #fafafa;
}
.archetypeEditorControls {
background: #fafafa;
&:before {
background: -webkit-linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
background: -moz-linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
background: linear-gradient(90deg, rgba(250,250,250,0), #fafafa);
}
}
form {
margin-left:20px;
@@ -219,25 +301,69 @@
border: 1px solid #b94a48;
}
.archetypeFooter {
text-align: center;
margin-top: 20px;
}
.archetypeAddButton {
color: #ddd;
.icon {
vertical-align: text-top;
}
display: inline-block;
height: 28px;
width: 28px;
line-height: 28px;
border-radius: 14px;
border: 1px solid #b6b6b6;
color: #5f5f5f;
background: white;
font-size: 16px;
text-align: center;
text-decoration: none;
cursor: pointer;
&:hover {
color: #333;
text-decoration: none;
cursor: pointer;
.archetypeAddButtonText {
text-decoration: underline;
}
.icon {
color: #333;
}
background: #00aea2;
border-color: #00aea2;
color: white;
}
}
.archetypeEmptyContent {
text-align: center;
margin-bottom: 20px;
span {
display: inline-block;
padding: 10px 20px;
clear: both;
font-size: 14px;
color: #555;
background: #f8f8f8;
border-radius: 15px;
}
}
.archetypeCrossDraggable + .archetypeEmptyContent {
margin-top: -42px;
}
&.archetypeDragging .archetypeCrossDraggable + .archetypeEmptyContent {
display: none;
}
// Necessary to ensure empty lists can be dropped onto when sorting nested fieldsets.
.archetypeSortable.archetypeEmpty.archetypeCrossDraggable {
min-height: 40px;
border: 1px dashed transparent;
}
&.archetypeDragging .archetypeSortable.archetypeEmpty.archetypeCrossDraggable {
min-height: 56px;
border-color: #dddddd;
}
.archetypeCollapser .archetypeEmptyContent span {
background: #f2f2f2;
}
.multiPropertyTextbox {
@@ -248,6 +374,9 @@
list-style: none;
margin-left: 0;
}
li {
line-height: 20px;
}
.show-validation.ng-invalid .control-group.error .control-label {
span {
@@ -263,6 +392,12 @@
overflow: visible;
vertical-align: top;
height: 90px;
.fieldsetPreviewOpen {
font-style: italic;
a:hover {
text-decoration: underline;
}
}
}
ul.groups {
display: block;
@@ -283,6 +418,66 @@
}
}
}
.fieldsetPreview {
.fieldsetPreviewClose {
font-style: italic;
font-size: 12px;
text-align: center;
}
.fieldsetPreviewImage {
padding: 6px 0px;
img {
height: auto;
max-width: 100%;
vertical-align: middle;
border: 0;
cursor: zoom-in;
}
}
}
}
.settingsWrapper {
&:hover {
caret {
background-color: #333;
}
}
.settingsHeader {
label {
display: inline-block;
}
&:hover {
cursor: pointer;
label {
text-decoration: underline;
}
.caret-right {
border-left-color: #333;
}
}
}
.settings {
padding: 14px;
background-color: #f8f8f8;
overflow: hidden;
.allowedGroups {
.umb-membergrouppicker a {
i {
padding-right: 0;
font-size: inherit;
}
&:hover i {
color: #333;
}
}
}
}
}
}
@@ -290,6 +485,7 @@
.archetypeEditorControls {
float: right;
}
.archetypeEditorControls, .archetypeFieldsetGroups {
i {
cursor: pointer;
@@ -315,10 +511,10 @@
small {
margin-left: 5px;
}
a {
float: right;
img {
width: 35px;
}
@@ -328,6 +524,26 @@
.manual-link {
color: blue;
}
.donate-link {
font-weight: 700;
}
.sponsors {
padding-bottom: 10px;
margin-bottom: 5px;
margin-left: 5px;
display: inline-table;
float: right;
a {
float: none;
}
h4 {
border-bottom: 1px solid #ccc;
}
}
ul {
list-style: none;
@@ -339,6 +555,7 @@
label {
width: 120px;
padding-left: 0;
}
.archetypeEditorControls {
@@ -347,6 +564,8 @@
.archetypeFieldsets {
margin-left: 0;
border-top: 5px solid;
padding-top: 5px;
}
.archetypeFieldsetWrapper {
@@ -362,8 +581,11 @@
.archetypeFieldsetOption {
margin-bottom: 15px;
input[type=text]{
max-width: 300px;
margin-right: 15px;
input[type=text] {
max-width: 100%;
width: 100%;
}
}
@@ -374,15 +596,20 @@
height: 130px;
}
.archetypeOptions label{
width: 400px;
.archetypeOptions {
.btn {
margin-bottom: 5px;
}
label {
width: 400px;
}
}
.archetypePropertiesWrapper {
border: 1px solid #ddd;
padding: 8px;
margin: -40px 10px 10px 140px;
max-width: 475px;
ul {
padding: 0;
@@ -395,12 +622,13 @@
background-color: #eee;
input[type=text] {
max-width: 190px;
width: auto;
max-width: 100%;
width: 100%;
}
select {
max-width: 160px;
max-width: 100%;
width: 100%;
}
}
@@ -414,6 +642,10 @@
width: 100%;
}
input[type=text] {
width: 100%;
}
input[type=checkbox] {
margin-top: 0;
margin-right: 2px;
@@ -444,10 +676,10 @@
}
}
}
}
}
}
.archetypeMaxFieldsets{
.archetypeMaxFieldsets {
border: 1px solid #ddd;
width: 40px;
text-align: right;
@@ -460,8 +692,10 @@
.archetypePropertyCollapser {
margin-top: 10px;
div {
margin-bottom: 10px;
margin-right: 15px;
}
}
@@ -472,6 +706,10 @@
.fieldsetIcon {
margin-right: 10px;
}
small {
color: #817f85;
}
}
.ui-sortable-placeholder {
@@ -6,6 +6,11 @@ angular.module('umbraco.resources').factory('archetypePropertyEditorResource', f
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAll"), 'Failed to retrieve datatypes from tree service'
);
},
getAllDataTypesForCache: function() {
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/GetAllDetails"), 'Failed to retrieve datatypes from tree service'
);
},
getDataType: function (guid, useDeepDatatypeLookup, contentTypeAlias, propertyTypeAlias, archetypeAlias, nodeId) {
if(useDeepDatatypeLookup) {
return umbRequestHelper.resourcePromise(
+70 -61
View File
@@ -1,78 +1,87 @@
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource) {
angular.module('umbraco.services').factory('archetypeCacheService', function (archetypePropertyEditorResource, $q, entityResource) {
//private
var isEntityLookupLoading = false;
var entityCache = [];
var isDatatypeLookupLoading = false;
var datatypeCache = [];
return {
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);
}
},
initialize: function() {
return archetypePropertyEditorResource.getAllDataTypesForCache().then(function(data) {
_.each(data, function(datatype) {
datatypeCache[datatype.dataTypeGuid] = datatype;
});
});
},
getDataTypeFromCache: function(guid) {
return datatypeCache[guid];
},
getDatatypeByGuid: function(guid) {
var cachedDatatype = this.getDataTypeFromCache(guid);
getDatatypeByGuid: function(guid) {
var cachedDatatype = this.getDataTypeFromCache(guid);
if(cachedDatatype) {
return cachedDatatype;
}
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;
return null;
},
getEntityById: function(scope, id, type) {
var cachedEntity = _.find(entityCache, function (e){
return e.id == id;
});
getEntityById: function(id, type) {
var deferred = $q.defer();
//console.log(entityCache);
var cachedEntity = entityCache[id];
if(cachedEntity) {
return cachedEntity;
}
if(cachedEntity) {
//console.log("Found ID " + id);
deferred.resolve(cachedEntity);
return deferred.promise;
}
//go get it from server
if (!isEntityLookupLoading) {
isEntityLookupLoading = true;
//go get it from server
entityResource.getById(id, type).then(function(entity) {
entityCache[id] = entity;
//console.log("entity ID is now resolved into cache...");
//console.log(entityCache);
deferred.resolve(entity);
});
scope.resources.entityResource.getById(id, type).then(function(entity) {
return deferred.promise;
},
entityCache.push(entity);
//perhaps this should return a promise?
getEntityByUmbracoId: function(udi, type) {
var deferred = $q.defer();
var cachedEntity = entityCache[udi];
isEntityLookupLoading = false;
if(cachedEntity) {
//console.log("Found UDI " + udi);
deferred.resolve(cachedEntity);
return deferred.promise;
}
return entity;
});
}
//go get it from server
entityResource.getByIds([udi], type).then(function (entities) {
// prevent infinite lookups with a default entity
var entity = entities.length > 0 ? entities[0] : { udi: udi, name: "" };
return null;
}
entityCache[udi] = entity;
//console.log("entity UDI is now resolved into cache...");
//console.log(entityCache);
deferred.resolve(entity);
});
return deferred.promise;
}
}
});
@@ -0,0 +1,19 @@
angular.module('umbraco.services').factory('archetypeGlobalConfigService', function ($q, $http, umbRequestHelper) {
return {
globalSettings: function () {
return umbRequestHelper.resourcePromise(
$http.get("backoffice/ArchetypeApi/ArchetypeDataType/globalSettings"), 'Failed to get whether or not we are checking for updates!'
);
},
setCheckForUpdates: function (isChecking) {
return umbRequestHelper.resourcePromise(
$http.post("backoffice/ArchetypeApi/ArchetypeDataType/SetCheckForUpdates", isChecking), 'Failed to update check status!'
);
},
checkForUpdates: function () {
return umbRequestHelper.resourcePromise(
$http.post("backoffice/ArchetypeApi/ArchetypeDataType/checkForUpdates", { }), 'Failed to check for updates!'
);
}
}
});
+412 -95
View File
@@ -1,6 +1,172 @@
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService) {
angular.module('umbraco.services').factory('archetypeLabelService', function (archetypeCacheService, $q, $injector, $timeout) {
//private
/**
* This will repeatedly wait for all promises in an array of promises to resolve, and it allows
* for promises to be added to the array (i.e., if you add more promises, those added promises
* will also be resolved too).
* @param promises The array of promises.
* @returns {*} The promise that will resolve once all promises in the array resolve.
*/
function repeatedlyWaitForPromises(promises) {
// Remember the original number of promises being resolved.
var originalLength = promises.length;
return $q.all(promises).then(function () {
// If there are new promises, resolve those too.
if (promises.length > originalLength) {
promises = promises.slice(originalLength);
return repeatedlyWaitForPromises(promises);
}
});
}
/**
* Processes a value to be used in a fieldset label. Since it might be a promise or a function, the
* value is repeatedly processed until it becomes a string.
* @param labelValue The value to be used in the fieldset label.
* @param promises The collection of promises to add any promises to.
* @param match The current matched substring object in a label template.
*/
function processLabelValue(labelValue, promises, match) {
// Normalize null/undefined values to an empty string.
if(!labelValue) {
labelValue = "";
}
// Check the type of value (may be a string, promise, function, or other).
if (isString(labelValue)) {
// handle collapsing dollar signs in labels (#387)
if (labelValue.indexOf("$$") >= 0) {
labelValue = labelValue.replace(/\$\$/g, "$$$$$$$$");
}
// Set a new value now that it has been processed.
//console.log("Processing string..." + labelValue);
match.value = labelValue;
} else if (isPromise(labelValue)) {
// Remember the promise so we can wait for it to be completed before constructing the
// fieldset label.
promises.push(labelValue);
labelValue.then(function (value) {
//console.log("Processing final value..." + value);
// The value will probably be a string, but recursively process it in case it's
// something else.
processLabelValue(value, promises, match);
});
} else if (_.isFunction(labelValue)) {
// Allow for the function to accept injected parameters, and invoke it.
labelValue = $injector.invoke(labelValue);
// Recursively check result (may be a string, promise, or another function (another
// function would be pretty strange, though I see no reason to disallow it).
processLabelValue(labelValue, promises, match);
} else {
// Some other data type (e.g., number, date, object).
match.value = labelValue;
}
}
/**
* Checks if the specified value is of type string.
* @param value The value to check the type of.
* @returns {boolean} True, if the value is a string; otherwise, false.
*/
function isString(value) {
if (value === null) {
return false;
} else if (typeof value === 'string') {
return true;
} else if (value instanceof String) {
return true;
} else {
return false;
}
}
/**
* Checks if the specified value is a JavaScript promise.
* @param value The value that may be a promise.
* @returns {*} True, if the value appears to be a promise; otherwise, false.
*/
function isPromise(value) {
return value && _.isFunction(value.then);
}
/**
* Splits a string value into a collection based on a regular expression.
* @param rgx The regular expression to use to find matches in the string value.
* @param value The string value to split.
* @returns {Array} A collection of objects, each representing a portion of the supplied
* string. Each object will contain the substring value, as well as a property
* indicating whether or not that substring was matched the regular expression.
*/
function splitByRegex(rgx, value) {
// Validate input.
if (!rgx || !value) {
return [];
}
// Variables.
var substring,
splitParts = [],
nextIndex = 0,
index;
// Reset regex so we get all the matches.
rgx.lastIndex = 0;
// Loop through each match until there are no more matches.
var match = rgx.exec(value);
while (match) {
// Extract match index.
index = match.index;
// Is there text between the prior match and this one?
if (nextIndex < index) {
substring = value.substring(nextIndex, index);
splitParts.push({
isMatch: false,
value: substring
});
}
// Remember the end of this match for the next loop iteration.
nextIndex = rgx.lastIndex;
// Store info about this match.
substring = value.substring(index, nextIndex);
splitParts.push({
isMatch: true,
value: substring
});
// Get next match.
match = rgx.exec(value);
}
// The text after the last match.
if (nextIndex < value.length) {
substring = value.substring(nextIndex);
splitParts.push({
isMatch: false,
value: substring
});
}
// Reset regex in case somebody else wants to use it.
rgx.lastIndex = 0;
// Return information about the matches.
return splitParts;
}
function executeFunctionByName(functionName, context) {
var args = Array.prototype.slice.call(arguments).splice(2);
@@ -19,21 +185,31 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
}
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 "";
}
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.MultiNodeTreePicker2":
return coreMntpV2(value, scope, datatype);
case "Umbraco.MultipleMediaPicker":
case "Umbraco.MediaPicker":
return coreMediaPicker(value, scope, datatype);
case "Umbraco.MediaPicker2":
return coreMediaPickerV2(value, scope, datatype);
case "Umbraco.DropDown":
return coreDropdown(value, scope, datatype);
case "RJP.MultiUrlPicker":
return rjpMultiUrlPicker(value, scope, {});
case "Umbraco.ContentPickerAlias":
return coreContentPicker(value, scope, datatype);
case "Umbraco.ContentPicker2":
return coreContentPickerV2(value, scope, datatype);
default:
return null;
}
}
function coreDropdown(value, scope, args) {
@@ -53,6 +229,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
function coreMntp(value, scope, args) {
var ids = value.split(',');
var type = "Document";
var deferred = $q.defer();
switch(args.preValues[0].value.type) {
case 'content':
@@ -64,129 +241,264 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
case 'member':
type = 'member';
break;
default:
break;
}
var entityArray = [];
var promises = [];
_.each(ids, function(id){
if(id) {
var entity = archetypeCacheService.getEntityById(scope, id, type);
if(entity) {
entityArray.push(entity.name);
}
promises.push(archetypeCacheService.getEntityById(id, type).then(function(entity){
if(entity) {
entityArray.push(entity.name);
}
}).promise);
}
});
return entityArray.join(', ');
$q.all(promises).then(function() {
deferred.resolve(entityArray.join(', '));
});
return deferred.promise;
}
function coreMntpV2(value, scope, args) {
var deferred = $q.defer();
var ids = value.split(',');
if (ids.length == 0) {
return "";
}
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 = [];
var promises = [];
_.each(ids, function (id) {
if(id) {
promises.push(archetypeCacheService.getEntityByUmbracoId(id, type).then(function(entity) {
if(entity) {
entityArray.push(entity.name);
}
}).promise);
}
});
$q.all(promises).then(function() {
if(entityArray.length == 0) {
deferred.resolve("");
}
var firstEntityName = entityArray[0];
var value = firstEntityName + (ids.length > 1 ? ", ..." : "");
deferred.resolve(value);
});
return deferred.promise;
}
function coreMediaPicker(value, scope, args) {
var deferred = $q.defer();
if(value) {
var entity = archetypeCacheService.getEntityById(scope, value, "media");
if(entity) {
return entity.name;
}
archetypeCacheService.getEntityById(value, "media").then(function(entity) {
deferred.resolve(entity.name);
});
}
else
{
deferred.resolve("");
}
return "";
return deferred.promise;
}
function coreMediaPickerV2(value, scope, args) {
var deferred = $q.defer();
//console.log("value=");
//console.log(value);
if(value) {
archetypeCacheService.getEntityByUmbracoId(value, "media").then(function(entity) {
deferred.resolve(entity.name);
});
}
else
{
deferred.resolve("");
}
return deferred.promise;
}
function coreContentPicker(value, scope, args) {
var deferred = $q.defer();
if(value) {
archetypeCacheService.getEntityById(value, "document").then(function(entity) {
deferred.resolve(entity.name);
});
}
else
{
deferred.resolve("");
}
return deferred.promise;
}
function coreContentPickerV2(value, scope, args) {
var deferred = $q.defer();
if (value) {
archetypeCacheService.getEntityByUmbracoId(value, "document").then(function(entity) {
deferred.resolve(entity.name);
});
}
else
{
deferred.resolve("");
}
return deferred.promise;
}
function imulusUrlPicker(value, scope, args) {
var deferred = $q.defer();
if(!value) {
deferred.resolve("");
return deferred.promise;
}
if(!args.propertyName) {
args = {propertyName: "name"}
}
if(typeof(value) != "object") {
value = JSON.parse(value);
}
var entity;
//console.log("urlpicker value...");
//console.log(value);
if(value.length) {
value = value[0];
}
switch (value.type) {
case "content":
if(value.typeData.contentId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.contentId, "Document");
archetypeCacheService.getEntityById(value.typeData.contentId, "Document").then(function(entity) {
//console.log("Retrived entity from cache!");
//console.log("Resolving the entity name with " + entity[args.propertyName]);
deferred.resolve(entity[args.propertyName]);
});
}
break;
case "media":
if(value.typeData.mediaId) {
entity = archetypeCacheService.getEntityById(scope, value.typeData.mediaId, "Media");
archetypeCacheService.getEntityById(value.typeData.mediaId, "Media").then(function(entity) {
deferred.resolve(entity[args.propertyName]);
});
}
break;
case "url":
return value.typeData.url;
deferred.resolve(value.typeData.url);
return deferred.promise;
default:
break;
}
if(entity) {
return entity[args.propertyName];
}
return "";
return deferred.promise;
}
function coreTinyMce(value, scope, args) {
if(!args.contentLength) {
args = {contentLength: 50}
args = {contentLength: 160}
}
var suffix = "";
var strippedText = $("<div/>").html(value).text();
if(strippedText.length > args.contentLength) {
suffix = "…";
suffix = "…";
}
return strippedText.substring(0, args.contentLength) + suffix;
}
return {
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
function rjpMultiUrlPicker(values, scope, args) {
var names = [];
//console.log(scope.model.config);
_.each(values, function (value) {
if (value.name) {
names.push(value.name);
}
});
return names.join(", ");
}
return {
getFieldsetTitle: function(scope, fieldsetConfigModel, fieldsetIndex) {
if(!fieldsetConfigModel)
return "";
return $q.when("");
var fieldset = scope.model.value.fieldsets[fieldsetIndex];
var fieldsetConfig = scope.getConfigFieldsetByAlias(fieldset.alias);
var template = fieldsetConfigModel.labelTemplate;
var promises = [];
if (template.length < 1)
return fieldsetConfig.label;
return $q.when(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);
}
});
var rgx = /{{.*?}}/g;
var matches = splitByRegex(rgx, template);
_.each(matches, function (match) {
// Skip over substrings that didn't match the regex (they do not require a transformation).
if (!match.isMatch) {
return;
}
// split the template in case it consists of multiple property aliases and/or functions
var templates = match.replace("{{", '').replace("}}", '').split("|");
var templates = match.value.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 != "") {
if(templateLabelValue !== "") {
break;
}
@@ -197,7 +509,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
var endParamsIndexOf = template.indexOf(")");
//if passed a function
if(beginParamsIndexOf != -1 && endParamsIndexOf != -1)
if(beginParamsIndexOf !== -1 && endParamsIndexOf !== -1)
{
var functionName = template.substring(0, beginParamsIndexOf);
var propertyAlias = template.substring(beginParamsIndexOf + 1, endParamsIndexOf).split(',')[0];
@@ -206,7 +518,7 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
var beginArgsIndexOf = template.indexOf(',');
if(beginArgsIndexOf != -1) {
if(beginArgsIndexOf !== -1) {
var argsString = template.substring(beginArgsIndexOf + 1, endParamsIndexOf).trim();
@@ -214,52 +526,57 @@ angular.module('umbraco.services').factory('archetypeLabelService', function (ar
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;
return property.alias === propertyAlias;
});
if(propertyConfig) {
var datatype = archetypeCacheService.getDatatypeByGuid(propertyConfig.dataTypeGuid);
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;
}
}
if(datatype) {
//try to get built-in label
var label = getNativeLabel(datatype, rawValue, scope);
if (label) {
templateLabelValue = label;
}
}
}
else {
return templateLabelValue;
}
}
}
}
if(!templateLabelValue) {
templateLabelValue = "";
}
parsedTemplate = parsedTemplate.replace(match, templateLabelValue);
// Process the value (i.e., reduce any functions or promises down to strings).
processLabelValue(templateLabelValue, promises, match);
});
return parsedTemplate;
// Wait for all of the promises to resolve before constructing the full fieldset label.
return repeatedlyWaitForPromises(promises).then(function () {
//console.log("done waiting...")
// Extract string values and combine them into a single string.
var substrings = _.map(matches, function (value) {
return value.value;
});
var combinedSubstrings = substrings.join('');
//console.log(combinedSubstrings);
// Return the title.
return combinedSubstrings;
});
}
}
}
});
+129 -5
View File
@@ -1,4 +1,12 @@
angular.module('umbraco.services').factory('archetypeService', function () {
// Variables.
var draggedRteArchetype;
var archetypeEditors;
var rteClass = ".archetypeEditor .umb-rte textarea";
var editorSettings = {};
var disabledSortables = [];
//public
return {
//helper that returns a JS ojbect from 'value' string or the original string
@@ -44,7 +52,7 @@ angular.module('umbraco.services').factory('archetypeService', function () {
return property.alias == alias;
});
},
getUniquePropertyAlias: function (currentScope, propertyAliasParts) {
getUniquePropertyAlias: function (currentScope, propertyAliasParts, excludeUniqueId) {
if (currentScope.hasOwnProperty('fieldsetIndex') && currentScope.hasOwnProperty('property') && currentScope.hasOwnProperty('propertyConfigIndex'))
{
var currentPropertyAlias = "f" + currentScope.fieldsetIndex + "-" + currentScope.property.alias + "-p" + currentScope.propertyConfigIndex;
@@ -57,15 +65,23 @@ angular.module('umbraco.services').factory('archetypeService', function () {
}
if (currentScope.$parent)
this.getUniquePropertyAlias(currentScope.$parent, propertyAliasParts);
this.getUniquePropertyAlias(currentScope.$parent, propertyAliasParts, true);
return _.unique(propertyAliasParts).reverse().join("-");
var reversed = _.unique(propertyAliasParts).reverse();
if (!excludeUniqueId) {
reversed.push(_.uniqueId("u-"));
}
return reversed.join("-");
},
getFieldset: function(scope) {
return scope.archetypeRenderModel.fieldsets[scope.fieldsetIndex];
var renderModel = scope.archetypeRenderModel;
return renderModel ? renderModel.fieldsets[scope.fieldsetIndex] : null;
},
getFieldsetProperty: function (scope) {
return this.getFieldset(scope).properties[scope.renderModelPropertyIndex];
var fieldset = this.getFieldset(scope);
return fieldset ? fieldset.properties[scope.renderModelPropertyIndex] : null;
},
setFieldsetValidity: function (fieldset) {
// mark the entire fieldset as invalid if there are any invalid properties in the fieldset, otherwise mark it as valid
@@ -99,6 +115,114 @@ angular.module('umbraco.services').factory('archetypeService', function () {
// 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);
},
// This stores the rich text editors in all Archetypes (e.g., during a drag operation).
// Typically, the editors will be restored after the drag completes.
storeEditors: function (element) {
// If there are not tinyMCE editors, this may be undefined.
if (typeof tinyMCE === "undefined") {
return;
}
// Variables.
var self = this;
draggedRteArchetype = element;
// Empty the stored settings.
editorSettings = {};
// For fast lookups, store each editor by the element ID.
var editorsById = {};
for (var i = 0; i < tinyMCE.editors.length; i++) {
var tempEditor = tinyMCE.editors[i];
editorsById[tempEditor.id] = tempEditor;
}
// Process each rich text editor.
$(rteClass).each(function() {
// Variables.
var id = $(this).attr("id");
var editor = editorsById[id];
// Get the property's temporary ID.
var scope = angular.element(this).scope().$parent;
var property = self.getFieldsetProperty(scope);
var tempId = property ? property.editorState.temporaryId : null;
// Store the editor settings by the temporary ID?
if (editor && editor.settings && tempId) {
editorSettings[tempId] = editor.settings;
}
});
},
// This restores the rich text editors in the specified Archetype
// (e.g., after a drop drop operation).
restoreEditors: function(element) {
// If there are not tinyMCE editors, this may be undefined.
if (typeof tinyMCE === "undefined") {
return;
}
// Variables.
var bothElements = element
? element.add(draggedRteArchetype)
: draggedRteArchetype;
var self = this;
// Process each RTE in both Archetypes.
$(rteClass, bothElements).each(function () {
// Variables.
var id = $(this).attr("id");
// Get the stored editor settings.
var scope = angular.element(this).scope().$parent;
var property = self.getFieldsetProperty(scope);
var tempId = property ? property.editorState.temporaryId : null;
var settings = editorSettings[tempId];
// Remove and reinitialize the editor.
if (settings) {
tinyMCE.execCommand("mceRemoveEditor", false, id);
tinyMCE.init(settings);
}
});
},
// Ensures the specified property has a temporary ID in its editor state,
// optionally forcing one to be regenerated (if specified).
ensureTemporaryId: function(property, regenerateId) {
if (!property.editorState) {
property.editorState = {};
}
var editorState = property.editorState;
if (!editorState.temporaryId || regenerateId) {
editorState.temporaryId = _.uniqueId("property-temp-id-");
}
},
// Remembers a sortable that has been disabled (so it can be enabled later).
rememberDisabledSortable: function(sortable) {
disabledSortables.push(sortable);
},
// Enables all of the sortables that were disabled.
enableSortables: function() {
_.each(disabledSortables, function(sortable) {
sortable.enable();
});
disabledSortables = [];
},
// Get all active archetype editors on the current page
getEditors: function() {
if (archetypeEditors == null) {
archetypeEditors = $('.archetypeEditor');
}
return archetypeEditors;
}
}
});
@@ -3,29 +3,27 @@
<div class="umb-panel-body no-header with-footer umb-scrollable archetypeAdvancedOptions">
<h3><archetype-localize key="developer_options">Developer Options</archetype-localize></h3>
<div>
<label for="archetypeAdvancedOptionsDeepDatatypeRequest"><input type="checkbox" id="archetypeAdvancedOptionsDeepDatatypeRequest" ng-model="model.enableDeepDatatypeRequests"/><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>
<label for="archetypeAdvancedOptionsDeepDatatypeRequest"><input type="checkbox" id="archetypeAdvancedOptionsDeepDatatypeRequest" ng-model="dialogData.model.enableDeepDatatypeRequests" /><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>
</div>
<div>
<label for="archetypeAdvancedOptionsDeveloperMode"><input type="checkbox" id="archetypeAdvancedOptionsDeveloperMode" ng-model="model.developerMode"/><archetype-localize key="toggleDeveloperMode">Enable Developer Mode?</archetype-localize><small><archetype-localize key="toggleDeveloperModeDescription">Toggle Developer Mode</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsDeveloperMode"><input type="checkbox" id="archetypeAdvancedOptionsDeveloperMode" ng-model="dialogData.model.developerMode" /><archetype-localize key="toggleDeveloperMode">Enable Developer Mode?</archetype-localize><small><archetype-localize key="toggleDeveloperModeDescription">Toggle Developer Mode</archetype-localize></small></label>
</div>
<div>
<label for="archetypeOverrideDefaultConverter"><input type="checkbox" id="archetypeOverrideDefaultConverter" ng-model="model.overrideDefaultPropertyValueConverter" /><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>
<label for="archetypeOverrideDefaultConverter"><input type="checkbox" id="archetypeOverrideDefaultConverter" ng-model="dialogData.model.overrideDefaultPropertyValueConverter" /><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>
</div>
<div ng-controller="ArchetypeConfigGlobalOptionsController">
<label for="archetypeCheckForNewVersion"><input type="checkbox" id="archetypeCheckForNewVersion" ng-model="globalSettings.checkForNewVersion" ng-click="confirmCheckNewVersionChange();" /><archetype-localize key="checkForNewVersion">Automatically check for newer versions?</archetype-localize><small><archetype-localize key="checkForNewVersionDescription">Check this if you wish to be notified when a newer version of Archetype is available. This is a application level setting.</archetype-localize> <a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Information%20Collection%20Disclosure.md" target="_blank">Information Collection Disclosure</a></small></label>
</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="model"></textarea>
<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="dialogData.model" ng-change="dialogData.modelChanged = true"></textarea>
</div>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href="" ng-click="close()" class="btn btn-link">
<localize key="general_cancel" class="ng-isolate-scope ng-scope">Cancel</localize>
</a>
<button class="btn btn-primary" ng-click="apply()">
<archetype-localize key="button_apply">Apply</archetype-localize>
<button class="btn" ng-click="apply()">
<archetype-localize key="button_close">Close</archetype-localize>
</button>
</div>
</div>
+30 -18
View File
@@ -3,46 +3,62 @@
<div class="umb-panel-body no-header with-footer umb-scrollable archetypeAdvancedOptions">
<h3><archetype-localize key="global_fieldset_options">Global Fieldset Options</archetype-localize></h3>
<div>
<label for="archetypeAdvancedOptionsStartWithAddButton"><input type="checkbox" id="archetypeAdvancedOptionsStartWithAddButton" ng-model="model.startWithAddButton"/><archetype-localize key="startWithAddButton">Start With Add Button?</archetype-localize><small><archetype-localize key="startWithAddButtonDescription">Empty property shows an add button instead of providing a default fieldset.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsStartWithAddButton"><input type="checkbox" id="archetypeAdvancedOptionsStartWithAddButton" ng-model="dialogData.model.startWithAddButton"/><archetype-localize key="startWithAddButton">Start With Add Button?</archetype-localize><small><archetype-localize key="startWithAddButtonDescription">Empty property shows an add button instead of providing a default fieldset.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsHideLabels"><input type="checkbox" id="archetypeAdvancedOptionsHideLabels" ng-model="model.hidePropertyLabels"/><archetype-localize key="hidePropertyLabels">Hide Property Labels?</archetype-localize><small><archetype-localize key="hidePropertyLabelsDescription">Hides the property labels.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsHideLabels"><input type="checkbox" id="archetypeAdvancedOptionsHideLabels" ng-model="dialogData.model.hidePropertyLabels"/><archetype-localize key="hidePropertyLabels">Hide Property Labels?</archetype-localize><small><archetype-localize key="hidePropertyLabelsDescription">Hides the property labels.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsCollapsing"><input type="checkbox" id="archetypeAdvancedOptionsCollapsing" ng-model="model.enableCollapsing"/><archetype-localize key="enableCollapsing">Enable Collapsing?</archetype-localize><small><archetype-localize key="enableCollapsingDescription">Enable fieldset collapsing.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsCollapsing"><input type="checkbox" id="archetypeAdvancedOptionsCollapsing" ng-model="dialogData.model.enableCollapsing"/><archetype-localize key="enableCollapsing">Enable Collapsing?</archetype-localize><small><archetype-localize key="enableCollapsingDescription">Enable fieldset collapsing.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsMultipleOpen"><input type="checkbox" id="archetypeAdvancedOptionsMultipleOpen" ng-model="dialogData.model.enableMultipleOpen" /><archetype-localize key="enableMultipleOpen">Enable Multiple Open Fieldsets?</archetype-localize><small><archetype-localize key="enableMultipleOpenDescription">When fieldset collapsing is enabled, this allows multiple fieldsets to be open at the same time.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsMinFieldsets"><archetype-localize key="minFieldsets">Min Fieldsets</archetype-localize><small><archetype-localize key="minFieldsetsDescription">How many Fieldsets are required? Default is none.</archetype-localize></small></label>
<input type="number" id="archetypeAdvancedOptionsMinFieldsets" class="archetypeMaxFieldsets" ng-model="dialogData.model.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="model.maxFieldsets"/>
<input type="number" id="archetypeAdvancedOptionsMaxFieldsets" class="archetypeMaxFieldsets" ng-model="dialogData.model.maxFieldsets"/>
</div>
<h4><archetype-localize key="fieldsetControls">Fieldset controls</archetype-localize></h4>
<div>
<label for="archetypeAdvancedOptionsHideControls"><input type="checkbox" id="archetypeAdvancedOptionsHideControls" ng-model="model.hideFieldsetControls"/><archetype-localize key="hideFieldsetControls">Hide Fieldset Controls?</archetype-localize><small><archetype-localize key="hideFieldsetControlsDescription">Hides the fieldset add/remove/sort controls.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsHideControls"><input type="checkbox" id="archetypeAdvancedOptionsHideControls" ng-model="dialogData.model.hideFieldsetControls"/><archetype-localize key="hideFieldsetControls">Hide Fieldset Controls?</archetype-localize><small><archetype-localize key="hideFieldsetControlsDescription">Hides the fieldset add/remove/sort controls.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsCloning"><input type="checkbox" id="archetypeAdvancedOptionsCloning" ng-model="model.enableCloning"/><archetype-localize key="enableCloning">Enable Cloning?</archetype-localize><small><archetype-localize key="enableCloningDescription">Enable fieldset cloning.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsCloning"><input type="checkbox" id="archetypeAdvancedOptionsCloning" ng-model="dialogData.model.enableCloning"/><archetype-localize key="enableCloning">Enable Cloning?</archetype-localize><small><archetype-localize key="enableCloningDescription">Enable fieldset cloning.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsDisabling"><input type="checkbox" id="archetypeAdvancedOptionsDisabling" ng-model="model.enableDisabling" /><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>
<label for="archetypeAdvancedOptionsDisabling"><input type="checkbox" id="archetypeAdvancedOptionsDisabling" ng-model="dialogData.model.enableDisabling" /><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>
</div>
<div>
<label for="archetypeAdvancedOptionsPublishing"><input type="checkbox" id="archetypeAdvancedOptionsPublishing" ng-model="dialogData.model.enablePublishing" /><archetype-localize key="enablePublishing">Enable Fieldset Publishing?</archetype-localize><small><archetype-localize key="enablePublishingDescription">Allows fieldsets to be automatically published and/or unpublished.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsCrossDragging"><input type="checkbox" id="archetypeAdvancedOptionsCrossDragging" ng-model="dialogData.model.enableCrossDragging" /><archetype-localize key="enableCrossDragging">Enable Cross-Archetype Dragging?</archetype-localize><small><archetype-localize key="enableCrossDraggingDescription">Allows fieldsets to be dragged into other Archetypes.</archetype-localize></small></label>
</div>
<div>
<label for="archetypeAdvancedOptionsMemberGroups"><input type="checkbox" id="archetypeAdvancedOptionsMemberGroups" ng-model="dialogData.model.enableMemberGroups" /><archetype-localize key="enableMemberGroups">Enable Member Group Access?</archetype-localize><small><archetype-localize key="enableMemerGroupsDescription">Allows fieldsets to be displayed for specified member groups only.</archetype-localize></small></label>
</div>
<h4><archetype-localize key="multipleFieldsets">Multiple fieldsets</archetype-localize></h4>
<div>
<label for="archetypeAdvancedOptionsMultipleFieldsets"><input type="checkbox" id="archetypeAdvancedOptionsMultipleFieldsets" ng-model="model.enableMultipleFieldsets"/><archetype-localize key="enableMultipleFieldsets">Enable Multiple Fieldsets?</archetype-localize><small><archetype-localize key="enableMultipleFieldsetsDescription">Allows multiple types of fieldsets within this archetype.</archetype-localize></small></label>
<label for="archetypeAdvancedOptionsMultipleFieldsets"><input type="checkbox" id="archetypeAdvancedOptionsMultipleFieldsets" ng-model="dialogData.model.enableMultipleFieldsets"/><archetype-localize key="enableMultipleFieldsets">Enable Multiple Fieldsets?</archetype-localize><small><archetype-localize key="enableMultipleFieldsetsDescription">Allows multiple types of fieldsets within this archetype.</archetype-localize></small></label>
</div>
<div ng-show="model.enableMultipleFieldsets">
<div ng-show="dialogData.model.enableMultipleFieldsets">
<label><archetype-localize key="fieldsetGroups">Fieldset groups</archetype-localize></label>
<small><archetype-localize key="fieldsetGroupsDescription">If you have a lot of fieldsets to choose from, you may want to consider grouping them in the fieldset picker. Once you have created your groups here, a group picker will be displayed in the fieldset editor and you can assign your fieldsets to their respective groups.</archetype-localize></small>
<div class="archetypeFieldsetGroups">
<ul ui-sortable="sortableOptions" ng-model="model.fieldsetGroups">
<li ng-repeat="fieldsetGroup in model.fieldsetGroups">
<ul ui-sortable="sortableOptions" ng-model="dialogData.model.fieldsetGroups">
<li ng-repeat="fieldsetGroup in dialogData.model.fieldsetGroups">
<div>
<input id="archetypeFieldsetGroupName_{{$index}}" type="text" ng-model="fieldsetGroup.name" />
<i class="icon icon-delete" ng-click="removeFieldsetGroup($index)"></i>
<i class="icon icon-navigation handle" ng-show="model.fieldsetGroups.length > 1"></i>
<i class="icon icon-navigation handle" ng-show="dialogData.model.fieldsetGroups.length > 1"></i>
</div>
</li>
</ul>
@@ -53,12 +69,8 @@
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href="" ng-click="close()" class="btn btn-link">
<localize key="general_cancel" class="ng-isolate-scope ng-scope">Cancel</localize>
</a>
<button class="btn btn-primary" ng-click="apply()">
<archetype-localize key="button_apply">Apply</archetype-localize>
<button class="btn" ng-click="apply()">
<archetype-localize key="button_close">Close</archetype-localize>
</button>
</div>
</div>
+26 -9
View File
@@ -1,8 +1,17 @@
{{VERSION_HTML}}
<div class="archetypeConfig" ng-controller="Imulus.ArchetypeConfigController">
<h2 class="archetype-headline"><img src="../App_Plugins/Archetype/assets/logo_50.png"/>Archetype<small>{{dllVersion}}</small><a href="https://twitter.com/archetypekit" target="_blank"><img src="../App_Plugins/Archetype/assets/twitter.png"/></a></h2>
<p>At a minimum your Archetype needs at least one fieldset with at least one property. You can configure it to allow for multiple types of fieldsets within a single Archetype and you can even add another Archetype as a property. Please use the link below for the full manual:</p>
<p><a class="manual-link" href="https://github.com/kgiszewski/ArchetypeManual" target="_blank">Archetype Manual</a></p>
<h2 class="archetype-headline"><img src="../App_Plugins/Archetype/assets/logo_50.png"/>Archetype<small>{{dllVersion}}</small></h2>
<p>At a minimum your Archetype needs at least one fieldset with at least one property. Please use the link below for the full manual. We would really love a donation if you find Archetype useful. Your company can also sponsor a sprint!</p>
<p>
<a class="manual-link" href="https://github.com/kgiszewski/ArchetypeManual" target="_blank">Archetype Manual</a> |
<a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Information%20Collection%20Disclosure.md" target="_blank">Information Collection Disclosure</a> |
<a class="manual-link" href="https://www.youtube.com/watch?v=79LksNwGjLk" target="_blank">Quick Start Video</a> |
<a class="manual-link" href="https://twitter.com/archetypekit" target="_blank">Twitter</a> |
<a class="manual-link" href="https://github.com/kgiszewski/Archetype" target="_blank">GitHub</a> |
<a class="manual-link" href="https://github.com/kgiszewski/Archetype/blob/master/Sponsors.md" target="_blank">Become a sponsor</a> |
<a class="manual-link donate-link" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KBKWLURGLGU6L" target="_blank">Donate!</a>
</p>
<ul class="archetypeFieldsets" ui-sortable="sortableOptions" ng-model="archetypeConfigRenderModel.fieldsets">
<li ng-repeat="fieldset in archetypeConfigRenderModel.fieldsets" ng-hide="fieldset.remove">
<div class="archetypeFieldsetWrapper" >
@@ -12,14 +21,16 @@
<i class="icon icon-navigation handle" ng-show="canSortFieldset()"></i>
</div>
<div class="archetypeFieldsetTitle" ng-click="focusFieldset(fieldset)">{{fieldset.label}}</div>
<div class="archetypeFieldsetCollapser" ng-hide="fieldset.collapse && fieldset.label">
<div class="archetypeFieldsetCollapser" ng-hide="fieldset.collapse && fieldset.label" ng-if="isLoaded(fieldset)">
<div class="archetypeFieldsetOption">
<label for="archetypeFieldLabel_{{$index}}"><archetype-localize key="label">Label</archetype-localize></label>
<input type="text" id="archetypeFieldLabel_{{$index}}" ng-model="fieldset.label" on-keyup="autoPopulateAlias(this)" />
<input type="text" id="archetypeFieldLabel_{{$index}}" ng-model="fieldset.label" on-keyup="autoPopulateAlias(fieldset)" />
<small>The label shown to the editors when adding a new fieldset.</small>
</div>
<div class="archetypeFieldsetOption">
<label for="archetypeFieldAlias_{{$index}}"><archetype-localize key="alias">Alias</archetype-localize></label>
<input type="text" id="archetypeFieldAlias_{{$index}}" ng-model="fieldset.alias" on-keyup="markAliasDirty(this)" required/>
<input type="text" id="archetypeFieldAlias_{{$index}}" ng-model="fieldset.alias" on-keyup="markAliasDirty(fieldset)" required/>
<small>The alias used to identify the fieldset when rendering.</small>
</div>
<div class="archetypeFieldsetOption" ng-show="archetypeConfigRenderModel.fieldsetGroups.length">
<label for="archetypeFieldsetGroup_{{$index}}"><archetype-localize key="fieldsetGroup">Group</archetype-localize></label>
@@ -28,6 +39,12 @@
<div class="archetypeFieldsetOption">
<label for="archetypeFieldLabelTemplate_{{$index}}"><archetype-localize key="labelTemplate">Label Template</archetype-localize></label>
<input type="text" id="archetypeFieldLabelTemplate_{{$index}}" ng-model="fieldset.labelTemplate" />
<small>Generates labels per fieldset. Can contain property aliases, e.g. "Article: &#123;&#123;title&#125;&#125;".</small>
</div>
<div class="archetypeFieldsetOption">
<label for="archetypeFieldPreview_{{$index}}">Preview image</label>
<input type="text" id="archetypeFieldPreview_{{$index}}" ng-model="fieldset.previewImage" on-keyup="markAliasDirty(fieldset)" />
<small>A relative path to a preview image, e.g. "/assets/fieldset.png".</small>
</div>
<div class="archetypeFieldsetOption" ng-show="archetypeConfigRenderModel.enableMultipleFieldsets">
<label for="archetypeFieldIcon_{{$index}}"><archetype-localize key="icon">Icon</archetype-localize></label>
@@ -45,16 +62,16 @@
<i class="icon icon-navigation handle" ng-show="canSortProperty(fieldset)"></i>
</div>
<div class="archetypePropertyTitle" ng-click="focusProperty(fieldset.properties, property)">
{{property.label}} ({{property.alias}}) - <span>{{getDataTypeNameByGuid(property.dataTypeGuid)}}</span>
{{property.label}}<span ng-if="property.required" class="property-required">*</span> ({{property.alias}}) - <span>{{getDataTypeNameByGuid(property.dataTypeGuid)}}</span>
</div>
<div class="archetypePropertyCollapser" ng-hide="property.collapse && property.label">
<div>
<label for="archetypePropertyLabel_{{$parent.$index}}_{{$index}}"><archetype-localize key="label">Label</archetype-localize></label>
<input type="text" id="archetypePropertyLabel_{{$parent.$index}}_{{$index}}" ng-model="property.label" on-keyup="autoPopulateAlias(this)"/>
<input type="text" id="archetypePropertyLabel_{{$parent.$index}}_{{$index}}" ng-model="property.label" on-keyup="autoPopulateAlias(property)"/>
</div>
<div>
<label for="archetypePropertyAlias_{{$parent.$index}}_{{$index}}"><archetype-localize key="alias">Alias</archetype-localize></label>
<input type="text" id="archetypePropertyAlias_{{$parent.$index}}_{{$index}}" ng-model="property.alias" on-keyup="markAliasDirty(this)" required/>
<input type="text" id="archetypePropertyAlias_{{$parent.$index}}_{{$index}}" ng-model="property.alias" on-keyup="markAliasDirty(property)" required/>
</div>
<div>
<label for="archetypePropertyHelpText_{{$parent.$index}}_{{$index}}"><archetype-localize key="helpText">Help Text</archetype-localize></label>
@@ -4,30 +4,26 @@
<h3><archetype-localize key="custom_style_script_options">Custom Style/Script Options</archetype-localize></h3>
<div>
<label for="archetypeAdvancedOptionsCustomClass"><archetype-localize key="customWrapperClass">Custom Wrapper Class</archetype-localize><small><archetype-localize key="customWrapperClassDescription">(Optional) Enter a custom CSS class that will be applied to the wrapper div.</archetype-localize></small></label>
<input type="text" id="archetypeAdvancedOptionsCustomClass" ng-model="model.customCssClass"/>
<input type="text" id="archetypeAdvancedOptionsCustomClass" ng-model="dialogData.model.customCssClass"/>
</div>
<div>
<label for="archetypeAdvancedOptionsCustomCss"><archetype-localize key="cssFile">CSS File</archetype-localize><small><archetype-localize key="cssFileDescription">(Optional) Enter a path for a custom CSS file to be included on the page.</archetype-localize></small></label>
<input type="text" id="archetypeAdvancedOptionsCustomCss" ng-model="model.customCssPath"/>
<input type="text" id="archetypeAdvancedOptionsCustomCss" ng-model="dialogData.model.customCssPath"/>
</div>
<div>
<label for="archetypeAdvancedOptionsCustomJs"><archetype-localize key="jsFile">JS File</archetype-localize><small><archetype-localize key="jsFileDescription">(Optional) Enter a path for a custom JS file to be included on the page.</archetype-localize></small></label>
<input type="text" id="archetypeAdvancedOptionsCustomJs" ng-model="model.customJsPath"/>
<input type="text" id="archetypeAdvancedOptionsCustomJs" ng-model="dialogData.model.customJsPath"/>
</div>
<div>
<label for="archetypeAdvancedOptionsCustomView"><archetype-localize key="viewFile">View File</archetype-localize><small><archetype-localize key="viewFileDescription">(Optional) Enter a path for a custom view file to be used to render this Archetype.</archetype-localize></small></label>
<input type="text" id="archetypeAdvancedOptionsCustomView" ng-model="model.customViewPath"/>
<input type="text" id="archetypeAdvancedOptionsCustomView" ng-model="dialogData.model.customViewPath"/>
</div>
</div>
<div class="umb-panel-footer">
<div class="umb-el-wrap umb-panel-buttons">
<div class="btn-toolbar umb-btn-toolbar pull-right">
<a href="" ng-click="close()" class="btn btn-link">
<localize key="general_cancel" class="ng-isolate-scope ng-scope">Cancel</localize>
</a>
<button class="btn btn-primary" ng-click="apply()">
<archetype-localize key="button_apply">Apply</archetype-localize>
<button class="btn" ng-click="apply()">
<archetype-localize key="button_close">Close</archetype-localize>
</button>
</div>
</div>
+120 -30
View File
@@ -1,14 +1,23 @@
{{VERSION_HTML}}
<div class="archetypeEditor ng-class:model.config.customCssClass">
<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()">
<!-- Mandatory validation. -->
<input type="hidden" name="archetypeMandatory" ng-model="model.mandatoryValidation" ng-required="model.validation.mandatory" />
<div><span class="help-inline" val-msg-for="archetypeMandatory" val-toggle-msg="required"><archetype-localize key="required">Required</archetype-localize></span></div>
<!-- Min fieldsets validation. -->
<input type="hidden" name="archetypeMinFieldsets" ng-model="model.mandatoryMinFieldsets" ng-required="!minFieldsetsFulfilled()" />
<div><span class="help-inline" val-msg-for="archetypeMinFieldsets" val-toggle-msg="required">{{minFieldsetsMessage}}</span></div>
<!-- Fieldsets. -->
<ul ui-sortable="sortableOptions" class="archetypeSortable" ng-class="{archetypeEmpty: model.value.fieldsets.length === 0 || sortingLastItem(), archetypeCrossDraggable: model.config.enableCrossDragging}" ng-model="model.value.fieldsets">
<li ng-repeat="fieldset in model.value.fieldsets">
<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}">
<fieldset ng-class="['archetype-fieldset-' + fieldset.alias, (getFieldsetValidity(fieldset) == false ? 'archetypeFieldsetError' : ''), (isCollapsed(fieldset) ? '' : 'is-open')]" ng-init="fieldsetConfigModel = getConfigFieldsetByAlias(fieldset.alias)">
<div class="archetypeFieldsetLabel" ng-class="{enableCollapsing: model.config.enableCollapsing, dimmed: isDisabled(fieldset)}">
<div ng-click="focusFieldset(fieldset)" class="label-sub module-label">
<span class="caret" ng-hide="fieldset.collapse || !model.config.enableCollapsing"></span>
<span class="caret caret-right" ng-show="fieldset.collapse && model.config.enableCollapsing"></span>
<label ng-class="{dimmed: fieldset.disabled}">
<span class="caret" ng-class="{'caret-right': isCollapsed(fieldset)}" ng-show="model.config.enableCollapsing"></span>
<label>
<i class="fieldsetIcon icon ng-class:fieldsetConfigModel.icon"></i>
<span ng-bind="getFieldsetTitle(fieldsetConfigModel, $index)"></span>
</label>
@@ -17,14 +26,15 @@
<i class="icon icon-add" ng-show="canAdd()" ng-click="openFieldsetPicker($index, $event)"></i>
<i class="icon icon-navigation handle" ng-show="canSort()"></i>
<i class="icon icon-documents" ng-click="cloneRow($index)" ng-show="canClone()"></i>
<i class="icon icon-power" ng-click="enableDisable(fieldset)" ng-show="canDisable()"></i>
<i class="icon icon-delete" ng-click="removeRow($index)" ng-show="canRemove()"></i>
<i class="icon icon-eye" ng-class="{'icon-active': fieldset.disabled}" ng-click="enableDisable(fieldset)" ng-show="showDisableIcon(fieldset)"></i>
<i class="icon icon-time icon-disabled" ng-class="{'icon-active': isDisabledByPublishing(fieldset)}" ng-show="showPublishingIcon(fieldset)"></i>
<i class="icon icon-trash" ng-click="removeRow($index)" ng-show="canRemove()"></i>
</div>
</div>
<div class="archetypeCollapser animate-hide" ng-hide="model.config.enableCollapsing && isCollapsed(fieldset)" ng-if="!isCollapsed(fieldset)">
<div class="archetypeCollapser animate-hide" ng-hide="model.config.enableCollapsing && isCollapsed(fieldset)" ng-if="isLoaded(fieldset)">
<form class="form-inline">
<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}}">
<label ng-hide="model.config.hidePropertyLabels == '1'" class="control-label" for="archetype-property-{{model.alias}}-f{{$parent.$index}}-{{property.alias}}-p{{$index}}" ng-attr-title="{{ isDebuggingEnabled || model.config.developerMode ? property.alias : null }}">
<span>{{property.label}}</span>
<div class="archetypeFieldsetHelpText" ng-show="property.helpText">
<small>{{property.helpText}}</small>
@@ -36,37 +46,117 @@
<archetype-submit-watcher active-submit-watcher="activeSubmitWatcher" load-callback="submitWatcherOnLoad" submit-callback="submitWatcherOnSubmit"></archetype-submit-watcher>
</div>
</div>
<div class="control-group archetypeProperty settingsWrapper" ng-show="canConfigure()">
<div ng-click="showSettings = !showSettings" class="settingsHeader">
<span class="caret" ng-show="showSettings"></span>
<span class="caret caret-right" ng-hide="showSettings"></span>
<label>
<span><archetype-localize key="settings">Settings</archetype-localize></span>
</label>
</div>
<div class="settings" ng-show="showSettings">
<!-- misc fieldset settings go here -->
<div ng-if="fieldset.releaseDateModel" ng-show="canPublish()" class="control-group">
<label ng-hide="model.config.hidePropertyLabels == '1'" class="control-label">
<span><archetype-localize key="publish">Publishing</archetype-localize></span>
<div class="archetypeFieldsetHelpText">
<small><archetype-localize key="publishHelpText">Configure automatic publishing and/or unpublishing of this item</archetype-localize></small>
</div>
</label>
<div class="publishOptions" ng-class="[(model.config.hidePropertyLabels == '1' ? 'controls-no-label' : 'controls')]">
<div class="publishDate">
<label for="{{fieldset.releaseDateModel.alias}}">
<archetype-localize key="publishReleaseDate">Publish at</archetype-localize>
</label>
<umb-editor model="fieldset.releaseDateModel"></umb-editor>
</div>
<div class="publishDate">
<label for="{{fieldset.expireDateModel.alias}}">
<archetype-localize key="publishExpireDate">Unpublish at</archetype-localize>
</label>
<umb-editor model="fieldset.expireDateModel"></umb-editor>
</div>
<!-- we need a submit watcher here to make sure the publish dates are saved back to their models -->
<archetype-submit-watcher active-submit-watcher="activeSubmitWatcher" load-callback="submitWatcherOnLoad" submit-callback="submitWatcherOnSubmit"></archetype-submit-watcher>
</div>
</div>
<div ng-if="fieldset.allowedMemberGroupsModel" ng-show="canUseMemberGroups()" class="control-group allowedGroups">
<label ng-hide="model.config.hidePropertyLabels == '1'" class="control-label">
<span><archetype-localize key="allowedMemberGroups">Allowed member groups</archetype-localize></span>
<div class="archetypeFieldsetHelpText">
<small><archetype-localize key="allowedMemberGroupsHelpText">Choose the member groups that should be allowed to see this item. Leave empty to allow all member groups.</archetype-localize></small>
</div>
</label>
<div ng-class="[(model.config.hidePropertyLabels == '1' ? 'controls-no-label' : 'controls')]">
<umb-editor model="fieldset.allowedMemberGroupsModel"></umb-editor>
</div>
<!-- we need a submit watcher here to make sure the allowed member groups are saved back to the model -->
<archetype-submit-watcher active-submit-watcher="activeSubmitWatcher" load-callback="submitWatcherOnLoad" submit-callback="submitWatcherOnSubmit"></archetype-submit-watcher>
</div>
</div>
</div>
</form>
</div>
</fieldset>
</li>
</ul>
<div ng-show="showAddButton()">
<a class="archetypeAddButton" ng-click="openFieldsetPicker(0, $event)" prevent-default>
<i class="icon icon-add"></i>
<!-- Empty content display. -->
<div class="archetypeEmptyContent" ng-show="showEmptyContentHint()">
<span>
<archetype-localize key="addFieldset">Add an item</archetype-localize>
</span>
</div>
<!-- "Add" button. -->
<div class="archetypeFooter" ng-show="showAddButton()">
<a class="archetypeAddButton" ng-click="openFieldsetPicker(model.value.fieldsets.length, $event)" prevent-default>
<i class="icon icon-add"></i>
</a>
</div>
<!-- Fieldset picker. -->
<div class="usky-grid fieldsetPicker" ng-class="{withGroups: overlayMenu.fieldsetGroups.length > 1}" ng-if="overlayMenu.show">
<div class="cell-tools-menu" ng-style="overlayMenu.style" delayed-mouseleave="closeFieldsetPicker()" archetype-click-outside="closeFieldsetPicker()">
<h5>
<archetype-localize key="addFieldset">Add an item</archetype-localize>
</h5>
<ul class="groups" ng-show="overlayMenu.fieldsetGroups.length > 1">
<li ng-repeat="fieldsetGroup in overlayMenu.fieldsetGroups" ng-class="{active: fieldsetGroup == overlayMenu.activeFieldsetGroup}">
<a ng-click="overlayMenu.activeFieldsetGroup = fieldsetGroup">
{{fieldsetGroup.name}}
<div ng-show="!overlayMenu.fieldsetPreview">
<h5>
<archetype-localize key="addFieldset">Add an item</archetype-localize>
</h5>
<ul class="groups" ng-show="overlayMenu.fieldsetGroups.length > 1">
<li ng-repeat="fieldsetGroup in overlayMenu.fieldsetGroups" ng-class="{active: fieldsetGroup == overlayMenu.activeFieldsetGroup}">
<a ng-click="overlayMenu.activeFieldsetGroup = fieldsetGroup">
{{fieldsetGroup.name}}
</a>
</li>
</ul>
<ul class="elements">
<li ng-repeat="fieldset in overlayMenu.activeFieldsetGroup.fieldsets">
<a ng-click="pickFieldset(fieldset.alias, overlayMenu.index)" href>
<i class="icon {{fieldset.icon}}"></i>
{{fieldset.label}}
</a>
<div class="fieldsetPreviewOpen" ng-if="fieldset.previewImage">
<a href ng-click="openFieldsetPreview(fieldset)"><archetype-localize key="previewFieldsetOpen">(see preview)</archetype-localize></a>
</div>
</li>
</ul>
</div>
<div ng-show="overlayMenu.fieldsetPreview" class="fieldsetPreview">
<h5>
<archetype-localize key="previewFieldsetHeader">Preview: </archetype-localize>{{overlayMenu.fieldsetPreview.label}}
</h5>
<div class="fieldsetPreviewClose">
<a href ng-click="closeFieldsetPreview()"><archetype-localize key="previewFieldsetClose">(close preview)</archetype-localize></a>
</div>
<div class="fieldsetPreviewImage">
<a href="{{overlayMenu.fieldsetPreview.previewImage}}" target="_blank">
<img ng-src="{{overlayMenu.fieldsetPreview.previewImage}}" />
</a>
</li>
</ul>
<ul class="elements">
<li ng-repeat="fieldset in overlayMenu.activeFieldsetGroup.fieldsets">
<a ng-click="pickFieldset(fieldset.alias, overlayMenu.index)" href>
<i class="icon {{fieldset.icon}}"></i>
{{fieldset.label}}
</a>
</li>
</ul>
</div>
<div class="fieldsetPreviewClose">
<a href ng-click="closeFieldsetPreview()"><archetype-localize key="previewFieldsetClose">(close preview)</archetype-localize></a>
</div>
</div>
</div>
</div>
</div>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

+4 -4
View File
@@ -1,9 +1,9 @@
{
"name": "Archetype",
"version": "1.12.1",
"url": "http://github.com/imulus/archetype/",
"author": "Imulus - Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Et. Al.",
"authorUrl": "http://imulus.com/",
"version": "1.17.1",
"url": "http://github.com/kgiszewski/archetype/",
"author": "Kevin Giszewski - Tom Fulton - Lee Kelleher - Matt Brailsford - Kenn Jacobsen - Nicholas Westby - Et. Al.",
"authorUrl": "http://github.com/kgiszewski/archetype/",
"license": "MIT",
"licenseUrl": "http://opensource.org/licenses/MIT"
}
+6 -6
View File
@@ -4,15 +4,15 @@
<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>
<authors>kgiszewski, tomfulton</authors>
<owners>kgiszewski, tomfulton</owners>
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
<description><![CDATA[Archetype for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://github.com/imulus/archetype/raw/master/assets/logo.png</iconUrl>
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
<dependencies>
<dependency id="UmbracoCms.Core" version="7.2.2" />
<dependency id="Archetype.Binaries" version="<%= version %>" />
</dependencies>
</metadata>
</package>
</package>
-39
View File
@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<umbPackage>
<info>
<package>
<name><%= name %></name>
<version><%= version %></version>
<license url="<%= licenseUrl %>"><%= license %></license>
<url><%= url %></url>
<requirements>
<major>0</major>
<minor>0</minor>
<patch>0</patch>
</requirements>
</package>
<author>
<name><%= author %></name>
<website><%= authorUrl %></website>
</author>
<readme><![CDATA[<%= readmeContents %>]]></readme>
</info>
<DocumentTypes />
<Templates />
<Stylesheets />
<Macros />
<DictionaryItems />
<Languages />
<DataTypes />
<control />
<Actions />
<files>
<% files.forEach(function(file) { %>
<file>
<guid><%= file.guid %>.<%= file.ext %></guid>
<orgPath><%= file.dir %></orgPath>
<orgName><%= file.name %></orgName>
</file>
<% }); %>
</files>
</umbPackage>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Archetype.Binaries</id>
<version><%= version %></version>
<title><%= name %></title>
<authors>kgiszewski, tomfulton</authors>
<owners>kgiszewski, tomfulton</owners>
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
<description><![CDATA[Archetype binaries for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
<dependencies>
<dependency id="UmbracoCms.Core" version="7.2.2" />
</dependencies>
</metadata>
</package>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Archetype.Courier</id>
<version><%= version %></version>
<title><%= name %></title>
<authors>leekelleher</authors>
<owners>kgiszewski, leekelleher</owners>
<projectUrl>http://github.com/kgiszewski/archetype</projectUrl>
<description><![CDATA[Archetype Courier extension for Umbraco]]></description>
<tags>umbraco</tags>
<iconUrl>http://kgiszewski.github.io/Archetype/images/logo.png</iconUrl>
<licenseUrl><%= licenseUrl %></licenseUrl>
<dependencies>
<dependency id="Archetype.Binaries" version="<%= version %>" />
</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.6"
"grunt-umbraco-package": "^1.0.0"
},
"repository": {
"type": "git",