-
Notifications
You must be signed in to change notification settings - Fork 26
Copy & Paste feature #44
Changes from 4 commits
4866998
07368fe
3b19f86
f291957
b0e3d35
d21d66e
faf4aff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,40 +3,40 @@ | |
"$scope", | ||
"editorState", | ||
"notificationsService", | ||
"localStorageService", | ||
"innerContentService", | ||
"Our.Umbraco.StackedContent.Resources.StackedContentResources", | ||
|
||
function ($scope, editorState, notificationsService, innerContentService, scResources) { | ||
function ($scope, editorState, notificationsService, localStorageService, innerContentService, scResources) { | ||
|
||
$scope.inited = false; | ||
$scope.markup = {}; | ||
$scope.prompts = {}; | ||
$scope.model.value = $scope.model.value || []; | ||
|
||
$scope.contentTypeGuids = _.uniq($scope.model.config.contentTypes.map(function (itm) { | ||
return itm.icContentTypeGuid; | ||
})); | ||
|
||
$scope.canAdd = function () { | ||
return (!$scope.model.config.maxItems || $scope.model.config.maxItems === 0 || $scope.model.value.length < $scope.model.config.maxItems) && $scope.model.config.singleItemMode !== "1"; | ||
return (!$scope.model.config.maxItems || $scope.model.config.maxItems === "0" || $scope.model.value.length < $scope.model.config.maxItems) && $scope.model.config.singleItemMode !== "1"; | ||
}; | ||
|
||
$scope.canDelete = function () { | ||
return $scope.model.config.singleItemMode !== "1"; | ||
}; | ||
|
||
$scope.canCopy = function () { | ||
var test = "test"; | ||
try { | ||
window.localStorage.setItem(test, test); | ||
window.localStorage.removeItem(test); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
// TODO: Move this to InnerContent Service | ||
return localStorageService.isSupported; | ||
}; | ||
|
||
$scope.canPaste = function () { | ||
var stackedContentItem = JSON.parse(window.localStorage.getItem("StackedContentCopy")); | ||
if (stackedContentItem && validateModel(stackedContentItem)) return true; | ||
if ($scope.canCopy() && $scope.canAdd()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe canAdd should include a ls.isSupported check so you only need to check canAdd? Seems odd to check canCopy There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thinking was that you can't paste without copying it first. But yeah, we can replace it with |
||
return allowPaste; | ||
} | ||
return false; | ||
} | ||
}; | ||
|
||
$scope.addContent = function (evt, idx) { | ||
$scope.overlayConfig.event = evt; | ||
|
@@ -55,34 +55,35 @@ | |
setDirty(); | ||
}; | ||
|
||
$scope.copyToLocalStorage = function (evt, idx) { | ||
var stackedContentItem = JSON.parse(JSON.stringify($scope.model.value[idx])); | ||
stackedContentItem.key = ""; | ||
delete stackedContentItem.$$hashKey; | ||
|
||
if (validateModel(stackedContentItem)) { | ||
window.localStorage.setItem("StackedContentCopy", JSON.stringify(stackedContentItem)); | ||
notificationsService.success("Stacked Content", "Copied to clipboard."); | ||
return; | ||
$scope.copyContent = function (evt, idx) { | ||
// TODO: Move this to InnerContent Service | ||
var item = $scope.model.value[idx]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this need an ls.isSupperted check? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd thought about it, but the copy feature wouldn't be available if |
||
if (item && item.icContentTypeGuid) { | ||
localStorageService.set("icContentJson", JSON.stringify(item, function (k, v) { | ||
if (k === "key" || k === "$$hashKey") { | ||
return undefined; | ||
} | ||
return v; | ||
})); | ||
allowPaste = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced the allowPaste local variable is fool proof. Is there as possibility this could be false/true but there is something pastable int he clipboard? How expensive is the pastedAllowed() call? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It felt pretty expensive. I'd added a It felt overkill to get the data from localStorage, parse it and loop over the contentType GUIDs each time. There's mostly a clever way to handle this? |
||
notificationsService.success("Content", "The content block has been copied."); | ||
} else { | ||
notificationsService.error("Stacked Content", "Sorry, something went wrong."); | ||
notificationsService.error("Content", "Unfortunately, the content block was not able to be copied."); | ||
} | ||
} | ||
}; | ||
|
||
$scope.pasteFromLocalStorage = function (evt, idx) { | ||
var stackedContentItem = JSON.parse(window.localStorage.getItem("StackedContentCopy")); | ||
stackedContentItem.key = innerContentService.generateUid(); | ||
if (!stackedContentItem) { | ||
notificationsService.error("Stacked Content", "You need to copy content first."); | ||
return; | ||
} | ||
if (validateModel(stackedContentItem)) { | ||
$scope.overlayConfig.callback({ model: stackedContentItem, idx: idx, action: "add" }); | ||
return; | ||
$scope.pasteContent = function (evt, idx) { | ||
// TODO: Move this to InnerContent Service | ||
var item = JSON.parse(localStorageService.get("icContentJson")); | ||
item.key = innerContentService.generateUid(); | ||
|
||
if (contentValid(item)) { | ||
$scope.overlayConfig.callback({ model: item, idx: idx, action: "add" }); | ||
setDirty(); | ||
} else { | ||
notificationsService.error("Stacked Content", "Sorry, this content is not allowed here."); | ||
notificationsService.error("Content", "Unfortunately, the content block is not allowed to be pasted here."); | ||
} | ||
} | ||
}; | ||
|
||
$scope.sortableOptions = { | ||
axis: 'y', | ||
|
@@ -123,15 +124,22 @@ | |
} | ||
}; | ||
|
||
var validateModel = function (model) { | ||
try { | ||
if (!model || !model.icContentTypeGuid) return false; | ||
if (!$scope.model.config.contentTypes.filter(x => x.icContentTypeGuid === model.icContentTypeGuid).length) return false; | ||
return true; | ||
} catch (e) { | ||
return false; | ||
var contentValid = function (itm) { | ||
return !!itm && !!itm.icContentTypeGuid && _.contains($scope.contentTypeGuids, itm.icContentTypeGuid); | ||
}; | ||
|
||
var pasteAllowed = function () { | ||
// TODO: Move this to InnerContent Service | ||
var json = localStorageService.get("icContentJson"); | ||
if (json !== null) { | ||
var item = JSON.parse(json); | ||
return item && contentValid(item); | ||
} | ||
} | ||
return false; | ||
}; | ||
|
||
// Storing the 'canPaste' check in a local variable, so that it doesn't need to be re-eval'd every time | ||
var allowPaste = pasteAllowed(); | ||
|
||
// Set overlay config | ||
$scope.overlayConfig = { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,10 @@ | |
|
||
<div ng-show="inited"> | ||
|
||
<a ng-if="!model.value || model.value.length == 0" ng-click="addContent($event, 0)" class="placeholder" title="Add content"> | ||
<div ng-if="!model.value || model.value.length == 0"ng-click="addContent($event, 0)" class="placeholder" title="Add content"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something is wrong here. This should be two links side by side, but it appears the paste link is inside the add link. Needs refactoring. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd played around with various options - tried 2 |
||
<i class="icon icon-umb-contour"></i> | ||
</a> | ||
<a ng-click="pasteContent($event, 0)" ng-if="canPaste()" title="Paste content"><i class="icon icon-paste-in"></i></a> | ||
</div> | ||
|
||
<div ng-if="model.value && model.value.length > 0" class="stack__wrapper"> | ||
|
||
|
@@ -15,7 +16,7 @@ | |
<div class="stack__item" ng-repeat="itm in model.value"> | ||
<div class="stack__add-bar stack__add-bar--top" ng-if="model.config.singleItemMode !== '1'"> | ||
<a ng-click="addContent($event, $index)" class="stack__add-button" ng-if="canAdd()" title="Add"><i class="icon icon-add"></i></a> | ||
<a ng-click="pasteFromLocalStorage($event, $index)" class="stack__paste-button" ng-if="canPaste()" title="Paste"><i class="icon icon-paste-in"></i></a> | ||
<a ng-click="pasteContent($event, $index)" class="stack__paste-button" ng-if="canPaste()" title="Paste"><i class="icon icon-paste-in"></i></a> | ||
</div> | ||
<div class="stack__preview-wrapper"> | ||
<a ng-click="editContent($event, $index, itm)" class="stack__preview stack__preview--default" ng-if="!markup[itm.key]"> | ||
|
@@ -27,7 +28,7 @@ <h3>{{itm.name}}</h3> | |
</a> | ||
<div class="stack__buttons" ng-if="canDelete()" ng-mousedown="$event.stopPropagation();"> | ||
<div class="no-overflow"> | ||
<a ng-click="copyToLocalStorage($event, $index)" ng-if="canCopy()" class="stack__button" title="Copy"><i class="icon icon-documents"></i></a> | ||
<a ng-click="copyContent($event, $index)" ng-if="canCopy() && !prompts[itm.key]" class="stack__button" title="Copy"><i class="icon icon-documents"></i></a> | ||
<umb-confirm-action ng-if="prompts[itm.key]" | ||
direction="left" | ||
on-confirm="deleteContent($event, $index)" | ||
|
@@ -43,7 +44,7 @@ <h3>{{itm.name}}</h3> | |
|
||
<div class="stack__add-bar stack__add-bar--bottom" ng-if="model.config.singleItemMode !== '1'"> | ||
<a ng-click="addContent($event, model.value.length)" class="stack__add-button" ng-if="canAdd()" title="Add"><i class="icon icon-add"></i></a> | ||
<a ng-click="pasteFromLocalStorage($event, model.value.length)" class="stack__paste-button" ng-if="canPaste()" title="Paste"><i class="icon icon-paste-in"></i></a> | ||
<a ng-click="pasteContent($event, model.value.length)" class="stack__paste-button" ng-if="canPaste()" title="Paste"><i class="icon icon-paste-in"></i></a> | ||
</div> | ||
|
||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this always going to be string? Should we intParse then comapre?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that prevalues will be strings. This wasn't an issue previously, as we were using double-equals, so the JS was evaluating it. I'd tried to follow the ESLint rules by using the triple-equals, but the value was a string (based on my tests).