Compare commits

...

11 Commits

Author SHA1 Message Date
Niels Lyngsø a91d82b864 latest test version 2019-06-25 15:26:28 +02:00
Niels Lyngsø 6868581770 removed id 2019-06-25 15:26:06 +02:00
Niels Lyngsø 90e0fcb299 outcomment apporach on how to get media info to store in RTE content. 2019-06-13 08:27:39 +02:00
Niels Lyngsø 21abe5ff81 upload files to media library 2019-06-13 08:26:50 +02:00
Niels Lyngsø d0129caea4 Merge remote-tracking branch 'origin/v8/dev' into v8/feature/5577-trix-property-editor 2019-06-11 14:58:12 +02:00
Niels Lyngsø 66eac81fe8 AngularJS requires ngModel to be the fourth attribute... 2019-06-11 08:44:06 +02:00
Niels Lyngsø ae5122f4bb adding localization for notification when uploading a disallowed file type 2019-06-04 14:39:54 +02:00
Niels Lyngsø 6085d659e2 adding localizationService dependency 2019-06-04 14:39:18 +02:00
Niels Lyngsø 3675b3f40c First implementation of Trix 2019-06-04 14:23:40 +02:00
Niels Lyngsø e9eb1e9b45 Enable tokens in TranslateMeny 2019-06-04 14:23:19 +02:00
Niels Lyngsø 156fd1b4e6 Gulp tasks that enables working with the property-editor as App_Plugin from UI.Client 2019-06-04 14:22:58 +02:00
16 changed files with 868 additions and 15 deletions
+12 -6
View File
@@ -31,9 +31,14 @@ module.exports = {
umbraco: {files: ["./src/views/**/*.html"], folder: ""},
installer: {files: ["./src/installer/steps/*.html"], folder: "install/"}
},
plugins:{
app: {files: ["./src/App_Plugins/**/*"], folder: ""}
},
//globs for file-watching
globs:{
plugins: "./src/App_Plugins/**",
views: "./src/views/**/*.html",
less: "./src/less/**/*.less",
js: "./src/*.js",
@@ -41,12 +46,13 @@ module.exports = {
assets: "./src/assets/**"
}
},
root: "../Umbraco.Web.UI/Umbraco/",
root: "../Umbraco.Web.UI/",
targets: {
js: "js/",
lib: "lib/",
views: "views/",
css: "assets/css/",
assets: "assets/"
js: "Umbraco/js/",
lib: "Umbraco/lib/",
views: "Umbraco/views/",
plugins: "App_Plugins/",
css: "Umbraco/assets/css/",
assets: "Umbraco/assets/"
}
};
@@ -9,5 +9,5 @@ gulp.task('fastdev', function(cb) {
global.isProd = false;
runSequence(["dependencies", "js", "less", "views"], "watch", cb);
});
runSequence(["dependencies", "js", "less", "views", "plugins"], "watch", cb);
});
@@ -0,0 +1,25 @@
'use strict';
var config = require('../config');
var gulp = require('gulp');
var _ = require('lodash');
var MergeStream = require('merge-stream');
gulp.task('plugins', function () {
var stream = new MergeStream();
_.forEach(config.sources.plugins, function (group) {
console.log("copying " + group.files + " to " + config.root + config.targets.plugins + group.folder)
stream.add (
gulp.src(group.files)
.pipe( gulp.dest(config.root + config.targets.plugins + group.folder) )
);
});
return stream;
});
@@ -48,11 +48,18 @@ gulp.task('watch', function () {
.pipe(gulp.dest(config.root + config.targets.views))
);
//watch all app js files that will not be merged - copy single file changes
stream.add(
watch(config.sources.globs.js, { interval: watchInterval })
.pipe(gulp.dest(config.root + config.targets.js))
);
//watch all views - copy single file changes
stream.add(
watch(config.sources.globs.plugins, { interval: watchInterval })
.pipe(gulp.dest(config.root + config.targets.plugins))
);
return stream;
});
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Niels Hartvig
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 the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,2 @@
# umbraco-trix-editor
An Umbraco Property Editor that uses the Trix Richtext editor by Basecamp
@@ -0,0 +1,21 @@
{
// you can define multiple editors
propertyEditors: [
{
alias: "Umbraco.Core.Trix",
name: "Rich Text Editor — Trix",
icon: "icon-wand",
group: "Rich Content",
editor: {
view: "~/App_Plugins/TrixEditor/umbraco-trix.html",
"valueType": "TEXT"
}
}
]
,
javascript: [
'~/App_Plugins/TrixEditor/umbraco-trix.js',
'~/App_Plugins/TrixEditor/trix.directive.js'
]
}
@@ -0,0 +1,396 @@
@charset "UTF-8";
/*
Trix 1.1.1
Copyright © 2019 Basecamp, LLC
http://trix-editor.org/*/
trix-editor {
border: 1px solid #bbb;
border-radius: 3px;
margin: 0;
padding: 0.4em 0.6em;
min-height: 5em;
outline: none; }
trix-toolbar * {
box-sizing: border-box; }
trix-toolbar .trix-button-row {
display: flex;
flex-wrap: nowrap;
justify-content: space-between; }
trix-toolbar .trix-button-group {
display: flex;
margin-bottom: 10px;
border: 1px solid #bbb;
border-top-color: #ccc;
border-bottom-color: #888;
border-radius: 3px; }
trix-toolbar .trix-button-group:not(:first-child) {
margin-left: 1.5vw; }
@media (max-device-width: 768px) {
trix-toolbar .trix-button-group:not(:first-child) {
margin-left: 0; } }
trix-toolbar .trix-button-group-spacer {
flex-grow: 1; }
@media (max-device-width: 768px) {
trix-toolbar .trix-button-group-spacer {
display: none; } }
trix-toolbar .trix-button {
position: relative;
float: left;
color: rgba(0, 0, 0, 0.6);
font-size: 0.75em;
font-weight: 600;
white-space: nowrap;
padding: 0 0.5em;
margin: 0;
outline: none;
border: none;
border-bottom: 1px solid #ddd;
border-radius: 0;
background: transparent; }
trix-toolbar .trix-button:not(:first-child) {
border-left: 1px solid #ccc; }
trix-toolbar .trix-button.trix-active {
background: #cbeefa;
color: black; }
trix-toolbar .trix-button:not(:disabled) {
cursor: pointer; }
trix-toolbar .trix-button:disabled {
color: rgba(0, 0, 0, 0.125); }
@media (max-device-width: 768px) {
trix-toolbar .trix-button {
letter-spacing: -0.01em;
padding: 0 0.3em; } }
trix-toolbar .trix-button--icon {
font-size: inherit;
width: 2.6em;
height: 1.6em;
max-width: calc(0.8em + 4vw);
text-indent: -9999px; }
@media (max-device-width: 768px) {
trix-toolbar .trix-button--icon {
height: 2em;
max-width: calc(0.8em + 3.5vw); } }
trix-toolbar .trix-button--icon::before {
display: inline-block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.6;
content: "";
background-position: center;
background-repeat: no-repeat;
background-size: contain; }
@media (max-device-width: 768px) {
trix-toolbar .trix-button--icon::before {
right: 6%;
left: 6%; } }
trix-toolbar .trix-button--icon.trix-active::before {
opacity: 1; }
trix-toolbar .trix-button--icon:disabled::before {
opacity: 0.125; }
trix-toolbar .trix-button--icon-bold::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M15.6%2011.8c1-.7%201.6-1.8%201.6-2.8a4%204%200%200%200-4-4H7v14h7c2.1%200%203.7-1.7%203.7-3.8%200-1.5-.8-2.8-2.1-3.4zM10%207.5h3a1.5%201.5%200%201%201%200%203h-3v-3zm3.5%209H10v-3h3.5a1.5%201.5%200%201%201%200%203z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-italic::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M10%205v3h2.2l-3.4%208H6v3h8v-3h-2.2l3.4-8H18V5h-8z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-link::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M9.88%2013.7a4.3%204.3%200%200%201%200-6.07l3.37-3.37a4.26%204.26%200%200%201%206.07%200%204.3%204.3%200%200%201%200%206.06l-1.96%201.72a.91.91%200%201%201-1.3-1.3l1.97-1.71a2.46%202.46%200%200%200-3.48-3.48l-3.38%203.37a2.46%202.46%200%200%200%200%203.48.91.91%200%201%201-1.3%201.3z%22%2F%3E%3Cpath%20d%3D%22M4.25%2019.46a4.3%204.3%200%200%201%200-6.07l1.93-1.9a.91.91%200%201%201%201.3%201.3l-1.93%201.9a2.46%202.46%200%200%200%203.48%203.48l3.37-3.38c.96-.96.96-2.52%200-3.48a.91.91%200%201%201%201.3-1.3%204.3%204.3%200%200%201%200%206.07l-3.38%203.38a4.26%204.26%200%200%201-6.07%200z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-strike::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.73%2014l.28.14c.26.15.45.3.57.44.12.14.18.3.18.5%200%20.3-.15.56-.44.75-.3.2-.76.3-1.39.3A13.52%2013.52%200%200%201%207%2014.95v3.37a10.64%2010.64%200%200%200%204.84.88c1.26%200%202.35-.19%203.28-.56.93-.37%201.64-.9%202.14-1.57s.74-1.45.74-2.32c0-.26-.02-.51-.06-.75h-5.21zm-5.5-4c-.08-.34-.12-.7-.12-1.1%200-1.29.52-2.3%201.58-3.02%201.05-.72%202.5-1.08%204.34-1.08%201.62%200%203.28.34%204.97%201l-1.3%202.93c-1.47-.6-2.73-.9-3.8-.9-.55%200-.96.08-1.2.26-.26.17-.38.38-.38.64%200%20.27.16.52.48.74.17.12.53.3%201.05.53H7.23zM3%2013h18v-2H3v2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-quote::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M6%2017h3l2-4V7H5v6h3zm8%200h3l2-4V7h-6v6h3z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-heading-1::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12%209v3H9v7H6v-7H3V9h9zM8%204h14v3h-6v12h-3V7H8V4z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-code::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.2%2012L15%2015.2l1.4%201.4L21%2012l-4.6-4.6L15%208.8l3.2%203.2zM5.8%2012L9%208.8%207.6%207.4%203%2012l4.6%204.6L9%2015.2%205.8%2012z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-bullet-list::before {
background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%204a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm4%203h14v-2H8v2zm0-6h14v-2H8v2zm0-8v2h14V5H8z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-number-list::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M2%2017h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1%203h1.8L2%2013.1v.9h3v-1H3.2L5%2010.9V10H2v1zm5-6v2h14V5H7zm0%2014h14v-2H7v2zm0-6h14v-2H7v2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-undo::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.5%208c-2.6%200-5%201-6.9%202.6L2%207v9h9l-3.6-3.6A8%208%200%200%201%2020%2016l2.4-.8a10.5%2010.5%200%200%200-10-7.2z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-redo::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.4%2010.6a10.5%2010.5%200%200%200-16.9%204.6L4%2016a8%208%200%200%201%2012.7-3.6L13%2016h9V7l-3.6%203.6z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-decrease-nesting-level::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-8.3-.3l2.8%202.9L6%2014.2%204%2012l2-2-1.4-1.5L1%2012l.7.7zM3%205v2h19V5H3z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-button--icon-increase-nesting-level::before {
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-6.9-1L1%2014.2l1.4%201.4L6%2012l-.7-.7-2.8-2.8L1%209.9%203.1%2012zM3%205v2h19V5H3z%22%2F%3E%3C%2Fsvg%3E); }
trix-toolbar .trix-dialogs {
position: relative; }
trix-toolbar .trix-dialog {
position: absolute;
top: 0;
left: 0;
right: 0;
font-size: 0.75em;
padding: 15px 10px;
background: #fff;
box-shadow: 0 0.3em 1em #ccc;
border-top: 2px solid #888;
border-radius: 5px;
z-index: 5; }
trix-toolbar .trix-input--dialog {
font-size: inherit;
font-weight: normal;
padding: 0.5em 0.8em;
margin: 0 10px 0 0;
border-radius: 3px;
border: 1px solid #bbb;
background-color: #fff;
box-shadow: none;
outline: none;
-webkit-appearance: none;
-moz-appearance: none; }
trix-toolbar .trix-input--dialog.validate:invalid {
box-shadow: #F00 0px 0px 1.5px 1px; }
trix-toolbar .trix-button--dialog {
font-size: inherit;
padding: 0.5em;
border-bottom: none; }
trix-toolbar .trix-dialog--link {
max-width: 600px; }
trix-toolbar .trix-dialog__link-fields {
display: flex;
align-items: baseline; }
trix-toolbar .trix-dialog__link-fields .trix-input {
flex: 1; }
trix-toolbar .trix-dialog__link-fields .trix-button-group {
flex: 0 0 content;
margin: 0; }
trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
trix-editor [data-trix-mutable]::-moz-selection,
trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection {
background: none; }
trix-editor [data-trix-mutable]::selection,
trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection {
background: none; }
trix-editor [data-trix-mutable].attachment__caption-editor:focus::-moz-selection {
background: highlight; }
trix-editor [data-trix-mutable].attachment__caption-editor:focus::selection {
background: highlight; }
trix-editor [data-trix-mutable].attachment.attachment--file {
box-shadow: 0 0 0 2px highlight;
border-color: transparent; }
trix-editor [data-trix-mutable].attachment img {
box-shadow: 0 0 0 2px highlight; }
trix-editor .attachment {
position: relative; }
trix-editor .attachment:hover {
cursor: default; }
trix-editor .attachment--preview .attachment__caption:hover {
cursor: text; }
trix-editor .attachment__progress {
position: absolute;
z-index: 1;
height: 20px;
top: calc(50% - 10px);
left: 5%;
width: 90%;
opacity: 0.9;
transition: opacity 200ms ease-in; }
trix-editor .attachment__progress[value="100"] {
opacity: 0; }
trix-editor .attachment__caption-editor {
display: inline-block;
width: 100%;
margin: 0;
padding: 0;
font-size: inherit;
font-family: inherit;
line-height: inherit;
color: inherit;
text-align: center;
vertical-align: top;
border: none;
outline: none;
-webkit-appearance: none;
-moz-appearance: none; }
trix-editor .attachment__toolbar {
position: absolute;
z-index: 1;
top: -0.9em;
left: 0;
width: 100%;
text-align: center; }
trix-editor .trix-button-group {
display: inline-flex; }
trix-editor .trix-button {
position: relative;
float: left;
color: #666;
white-space: nowrap;
font-size: 80%;
padding: 0 0.8em;
margin: 0;
outline: none;
border: none;
border-radius: 0;
background: transparent; }
trix-editor .trix-button:not(:first-child) {
border-left: 1px solid #ccc; }
trix-editor .trix-button.trix-active {
background: #cbeefa; }
trix-editor .trix-button:not(:disabled) {
cursor: pointer; }
trix-editor .trix-button--remove {
text-indent: -9999px;
display: inline-block;
padding: 0;
outline: none;
width: 1.8em;
height: 1.8em;
line-height: 1.8em;
border-radius: 50%;
background-color: #fff;
border: 2px solid highlight;
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.25); }
trix-editor .trix-button--remove::before {
display: inline-block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.7;
content: "";
background-image: url(data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.4L17.6%205%2012%2010.6%206.4%205%205%206.4l5.6%205.6L5%2017.6%206.4%2019l5.6-5.6%205.6%205.6%201.4-1.4-5.6-5.6z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E);
background-position: center;
background-repeat: no-repeat;
background-size: 90%; }
trix-editor .trix-button--remove:hover {
border-color: #333; }
trix-editor .trix-button--remove:hover::before {
opacity: 1; }
trix-editor .attachment__metadata-container {
position: relative; }
trix-editor .attachment__metadata {
position: absolute;
left: 50%;
top: 2em;
transform: translate(-50%, 0);
max-width: 90%;
padding: 0.1em 0.6em;
font-size: 0.8em;
color: #fff;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 3px; }
trix-editor .attachment__metadata .attachment__name {
display: inline-block;
max-width: 100%;
vertical-align: bottom;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }
trix-editor .attachment__metadata .attachment__size {
margin-left: 0.2em;
white-space: nowrap; }
@charset "UTF-8";
.trix-content {
line-height: 1.5; }
.trix-content * {
box-sizing: border-box; }
.trix-content h1 {
font-size: 1.2em;
line-height: 1.2;
margin: 0; }
.trix-content blockquote {
margin: 0 0 0 0.3em;
padding: 0 0 0 0.6em;
border-left: 0.3em solid #ccc; }
.trix-content pre {
display: inline-block;
width: 100%;
vertical-align: top;
font-family: monospace;
font-size: 0.9em;
margin: 0;
padding: 0.5em;
white-space: pre;
background-color: #eee;
overflow-x: auto; }
.trix-content ul, .trix-content ol, .trix-content li {
margin: 0;
padding: 0; }
.trix-content ul li, .trix-content ol li, .trix-content li li {
margin-left: 1em; }
.trix-content img {
max-width: 100%;
height: auto; }
.trix-content .attachment {
display: inline-block;
position: relative;
max-width: 100%;
margin: 0;
padding: 0; }
.trix-content .attachment a {
color: inherit;
text-decoration: none; }
.trix-content .attachment a:hover, .trix-content .attachment a:visited:hover {
color: inherit; }
.trix-content .attachment__caption {
padding: 0;
text-align: center; }
.trix-content .attachment__caption .attachment__name + .attachment__size::before {
content: ' · '; }
.trix-content .attachment--preview {
width: 100%;
text-align: center; }
.trix-content .attachment--preview .attachment__caption {
color: #666;
font-size: 0.9em;
line-height: 1.2; }
.trix-content .attachment--file {
color: #333;
line-height: 1;
margin: 0 2px 2px 0;
padding: 0.4em 1em;
border: 1px solid #bbb;
border-radius: 5px; }
.trix-content .attachment-gallery {
display: flex;
flex-wrap: wrap;
position: relative;
margin: 0;
padding: 0; }
.trix-content .attachment-gallery .attachment {
flex: 1 0 33%;
padding: 0 0.5em;
max-width: 33%; }
.trix-content .attachment-gallery.attachment-gallery--2 .attachment, .trix-content .attachment-gallery.attachment-gallery--4 .attachment {
flex-basis: 50%;
max-width: 50%; }
/** upload feature */
.trix-button--icon-attach::before {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItdXBsb2FkLWNsb3VkIj48cG9seWxpbmUgcG9pbnRzPSIxNiAxNiAxMiAxMiA4IDE2Ij48L3BvbHlsaW5lPjxsaW5lIHgxPSIxMiIgeTE9IjEyIiB4Mj0iMTIiIHkyPSIyMSI+PC9saW5lPjxwYXRoIGQ9Ik0yMC4zOSAxOC4zOUE1IDUgMCAwIDAgMTggOWgtMS4yNkE4IDggMCAxIDAgMyAxNi4zIj48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz0iMTYgMTYgMTIgMTIgOCAxNiI+PC9wb2x5bGluZT48L3N2Zz4=);
}
trix-toolbar .trix-dialog--attach {
max-width: 600px;
}
trix-toolbar .trix-dialog__attach-fields {
display: flex;
align-items: baseline;
}
trix-toolbar .trix-dialog__attach-fields .trix-input {
flex: 1;
}
trix-toolbar .trix-dialog__attach-fields .trix-button-group {
flex: 0 0 content;
margin: 0;
}
@@ -0,0 +1,326 @@
// https://github.com/sachinchoolur/angular-trix
(function() {
'use strict';
angular.module('umbraco.directives').directive('trixEditor', function(Upload, umbRequestHelper, localizationService, notificationsService) {
return {
restrict: 'E',
require: 'ngModel',
scope: {
/*
trixInitialize: '&',
trixChange: '&',
trixSelectionChange: '&',
trixFocus: '&',
trixBlur: '&',
trixFileAccept: '&',
trixAttachmentAdd: '&',
trixAttachmentRemove: '&'
*/
},
link: function($scope, element, attr, ngModel) {
// TODO: retrive from configuration:
var acceptedFileTypes = ["image/jpeg", "image/png"];
var maxFileSize = 37000000;
var editorElement = element[0];
function init() {
// if we have some content, apply it to the Trix RTE.
if (ngModel.$modelValue) {
editorElement.editor.loadHTML(ngModel.$modelValue);
}
editorElement.addEventListener('trix-change', update);
addUploadFeature();
}
function update() {
var html = editorElement.value;
ngModel.$setViewValue(html);
}
editorElement.addEventListener('trix-initialize', init);
// maintenance of ng-model
ngModel.$render = function() {
if (editorElement.editor) {
editorElement.editor.loadHTML(ngModel.$modelValue);
}
};
// Apply upload-dialog:
function addUploadFeature() {
var toolbar = editorElement.toolbarElement;
var ttools = toolbar.querySelector(".trix-button-group--text-tools");
var dialogs = toolbar.querySelector(".trix-dialogs");
var trixId = editorElement.trixId;
var buttonContent = `
<button type="button"
class="trix-button trix-button--icon trix-button--icon-attach"
data-trix-attribute="attach"
data-trix-key="+" title="Attach file" tabindex="-1">
</button>
`;
var dialogContent = `
<div class="trix-dialog trix-dialog--attach" data-trix-dialog="attach" data-trix-dialog-attribute="attach">
<div class="trix-dialog__attach-fields">
<input type="file" class="trix-input trix-input--dialog">
<div class="trix-button-group">
<input type="button" class="trix-button trix-button--dialog"
onclick="
var trix = document.querySelector('trix-editor[trix-id=\\'${trixId}\\']');
var fileElm = this.parentElement.parentElement.querySelector('input[type=\\'file\\']');
if ( fileElm.files.length == 0 ) {
console.log('nothing selected');
return;
}
var file = fileElm.files[0];
trix.editor.insertFile(file);
"
value="Attach" data-trix-method="removeAttribute">
<input type="button" class="trix-button trix-button--dialog" value="Cancel" data-trix-method="removeAttribute">
</div>
</div>
</div>
`;
// add attach icon button
ttools.insertAdjacentHTML("beforeend", buttonContent);
// add dialog
dialogs.insertAdjacentHTML("beforeend", dialogContent);
}
// handling of file uploads
editorElement.addEventListener('trix-file-accept', function(e) {
if (acceptedFileTypes.indexOf(e.file.type) !== -1) {
} else {
e.preventDefault();
localizationService.localizeMany([
"media_uploadFileDisallowedHeadline",
"media_uploadFileDisallowedDescription"
],
[
undefined,
[e.file.type]
]
).then(function (data) {
notificationsService.error(data[0], data[1]);
});
}
// Prevent attaching files > 1024 bytes
//if (event.file.size > 1024) {
// event.preventDefault()
//}
});
editorElement.addEventListener('trix-attachment-add', function(event) {
var attachment = event.attachment;
if (attachment.file) {
/*
// set caption
var editor = editorElement.editor;
var originalRange = editor.getSelectedRange()
var attachmentRange = editor.getDocument().getRangeOfAttachment(attachment)
editor.setSelectedRange(attachmentRange)
editor.activateAttribute("caption", "<Insert Caption>")
editor.setSelectedRange(originalRange)
*/
if (attachment.file.size == 0) {
attachment.remove();
return;
// You may personalize max_file_size
} else if (attachment.file.size > maxFileSize) {
attachment.remove();
return;
}
uploadAttachment(attachment);
}
});
var attachmentsQueue = [];
function uploadAttachment(attachment) {
attachmentsQueue.push(attachment);
uploadNextAttachment();
}
function uploadNextAttachment() {
if (attachmentsQueue.length > 0) {
uploadAttachmentToMedia(attachmentsQueue.shift());
}
}
function uploadAttachmentToMedia(attachment) {
var file = attachment.file;
//attachment.attachment.attributes = attachment.attachment.attributes.add("data-udi", ".................");
Upload.upload({
url: umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostAddFile"),
fields: {
'currentFolder': -1,
'contentTypeAlias': "umbracoAutoSelect",
'propertyAlias': "umbracoFile",
'path': file.path
},
file: file
})
.progress(function(evt) {
//if (file.uploadStat !== "done" && file.uploadStat !== "error") {
// calculate progress in percentage
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
// set percentage property on file
//file.uploadProgress = progressPercentage;
// set uploading status on file
//file.uploadStatus = "uploading";
console.log("progressPercentage:", progressPercentage);
attachment.setUploadProgress(progressPercentage);
//}
})
.success(function(data, status, headers, config) {
if (data.notifications && data.notifications.length > 0) {
// set error status on file
//file.uploadStatus = "error";
// Throw message back to user with the cause of the error
//file.serverErrorMessage = data.notifications[0].message;
// Put the file in the rejected pool
//scope.rejected.push(file);
} else {
// set done status on file
//file.uploadStatus = "done";
//file.uploadProgress = 100;
// set date/time for when done - used for sorting
//file.doneDate = new Date();
// Put the file in the done pool
//scope.done.push(file);
attachment.setUploadProgress(100);
console.log("File uploaded, data: ", data, attachment);
/*
var media = data.medias[0];
if(media) {
// set UDI.. so far it has only been posible for me to set this attribute, which becomes part of the data-trix-attachment attribute on the figure element.
attachment.setAttributes({"udi": media.Id});
// set the url, Trix will parse on this variable to the img element as src attribute.
attachment.setAttributes({"url": media.Url});
} else {
// something failed, so we will remove the file again.
attachment.remove();
}
*/
// TODO: Get the URL and UDI from upload response.. missing in response..
attachment.setAttributes(
{
"udi": "1234567890",
"url": "/media/uxsduzyq/umbraco_cloudportal_login.png"
}
);
}
//after processing, test if everthing is done
uploadNextAttachment();
})
.error(function(evt, status, headers, config) {
console.log("Attachment error...");
// set status done
file.uploadStatus = "error";
//if the service returns a detailed error
if (evt.InnerException) {
file.serverErrorMessage = evt.InnerException.ExceptionMessage;
//Check if its the common "too large file" exception
if (evt.InnerException.StackTrace &&
evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) {
file.serverErrorMessage = "File too large to upload";
}
} else if (evt.Message) {
file.serverErrorMessage = evt.Message;
}
// If file not found, server will return a 404 and display this message
if (status === 404) {
file.serverErrorMessage = "File not found";
}
//after processing, test if everthing is done
//scope.rejected.push(file);
attachment.remove();
uploadNextAttachment();
});
}
/*
function registerEvent(type, callbackMethod) {
element[0].addEventListener(type, function(e) {
if (type === 'trix-file-accept' && attrs.preventTrixFileAccept === 'true') {
e.preventDefault();
}
callbackMethod({
e: e,
editor: editorElement
});
});
};
registerEvent('trix-initialize', $scope.trixInitialize);
registerEvent('trix-change', $scope.trixChange);
registerEvent('trix-selection-change', $scope.trixSelectionChange);
registerEvent('trix-focus', $scope.trixFocus);
registerEvent('trix-blur', $scope.trixBlur);
registerEvent('trix-file-accept', $scope.trixFileAccept);
registerEvent('trix-attachment-add', $scope.trixAttachmentAdd);
registerEvent('trix-attachment-remove', $scope.trixAttachmentRemove);
*/
}
};
});
}());
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
<div ng-controller="Umbraco.Core.TrixController as vm">
<trix-editor ng-model="model.value"></trix-editor>
</div>
@@ -0,0 +1,14 @@
angular.module("umbraco").controller("Umbraco.Core.TrixController",
function ($scope, assetsService) {
assetsService.load(["~/App_Plugins/TrixEditor/trix.js"]).then(
function() {
}
);
// load the separate css for the editor to avoid it blocking our JavaScript loading
assetsService.loadCss("~/App_Plugins/TrixEditor/trix.css");
});
@@ -188,17 +188,22 @@ angular.module('umbraco.services')
* @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key'
* alternatively if no section is set such as 'key' then we assume the key is to be looked in
* the 'general' section
* @param {Array} tokens is an array of arrays which has will be containing parameter values for the key
* This replaces %0% and %1% etc in the dictionary key value with the passed in keys
*
* @returns {Array} An array of localized resource string in the same order
*/
localizeMany: function(keys) {
localizeMany: function(keys, tokens) {
if(keys){
tokens = tokens || [];
//The LocalizationService.localize promises we want to resolve
var promises = [];
for(var i = 0; i < keys.length; i++){
promises.push(service.localize(keys[i], undefined));
promises.push(service.localize(keys[i], tokens[i]));
}
return $q.all(promises).then(function(localizedValues){
@@ -307,7 +307,9 @@
<key alias="moveFailed">Flytning af mediet fejlede</key>
<key alias="copyFailed">Kopiering af mediet fejlede</key>
<key alias="createFolderFailed">Oprettelse af mappen under parent med id %0% fejlede</key>
<key alias="renameFolderFailed">Omdøbning af mappen med id %0% fejlede</key>
<key alias="renameFolderFailed">Omdøbning af mappen med id %0% fejlede</key>
<key alias="uploadFileDisallowedHeadline">Filtypen blev afvist</key>
<key alias="uploadFileDisallowedDescription">Kan ikke uploade filer af typen %0%, denne filtype er ikke godkendt</key>
</area>
<area alias="member">
<key alias="createNewMember">Opret et nyt medlem</key>
@@ -316,7 +316,9 @@
<key alias="moveFailed">Failed to move media</key>
<key alias="copyFailed">Failed to copy media</key>
<key alias="createFolderFailed">Failed to create a folder under parent id %0%</key>
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="uploadFileDisallowedHeadline">Filetype rejected</key>
<key alias="uploadFileDisallowedDescription">Cannot upload files of type %0%, it's not an approved file type</key>
</area>
<area alias="member">
<key alias="createNewMember">Create a new member</key>
@@ -321,7 +321,9 @@
<key alias="moveToSameFolderFailed">Parent and destination folders cannot be the same</key>
<key alias="copyFailed">Failed to copy media</key>
<key alias="createFolderFailed">Failed to create a folder under parent id %0%</key>
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="renameFolderFailed">Failed to rename the folder with id %0%</key>
<key alias="uploadFileDisallowedHeadline">Filetype rejected</key>
<key alias="uploadFileDisallowedDescription">Cannot upload files of type %0%, it's not an approved file type</key>
</area>
<area alias="member">
<key alias="createNewMember">Create a new member</key>