+
@@ -165,6 +181,10 @@ export default defineComponent({
padding: 32px;
}
}
+
+ &.no-padding .main {
+ padding: 0px;
+ }
}
.footer {
diff --git a/src/compositions/use-item/use-item.ts b/src/compositions/use-item/use-item.ts
index 173ef2b575..01284c5a55 100644
--- a/src/compositions/use-item/use-item.ts
+++ b/src/compositions/use-item/use-item.ts
@@ -44,6 +44,7 @@ export function useItem(collection: Ref
, primaryKey: Ref
+
+
+ Edit
+
+
+
[
{
diff --git a/src/styles/lib/_cropperjs.scss b/src/styles/lib/_cropperjs.scss
new file mode 100644
index 0000000000..aadc821564
--- /dev/null
+++ b/src/styles/lib/_cropperjs.scss
@@ -0,0 +1,273 @@
+.cropper-container {
+ position: relative;
+ font-size: 0;
+ line-height: 0;
+ direction: ltr;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -ms-touch-action: none;
+ touch-action: none;
+}
+
+.cropper-container img {
+ display: block;
+ width: 100%;
+ min-width: 0 !important;
+ max-width: none !important;
+ height: 100%;
+ min-height: 0 !important;
+ max-height: none !important;
+ image-orientation: 0deg;
+}
+
+.cropper-wrap-box,
+.cropper-canvas,
+.cropper-drag-box,
+.cropper-crop-box,
+.cropper-modal {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+.cropper-wrap-box,
+.cropper-canvas {
+ overflow: hidden;
+}
+
+.cropper-drag-box {
+ background-color: #fff;
+ opacity: 0;
+}
+
+.cropper-modal {
+ background-color: #000;
+ opacity: 0.5;
+}
+
+.cropper-view-box {
+ display: block;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ outline: 1px solid var(--primary);
+ outline-color: var(--primary-50);
+}
+
+.cropper-dashed {
+ position: absolute;
+ display: block;
+ border: 0 dashed #fff;
+ border-style: solid;
+ box-shadow: 0 0px 0px 1px rgba(0, 0, 0, 0.3);
+ opacity: 0.4;
+}
+
+.cropper-dashed.dashed-h {
+ top: calc(100% / 3);
+ left: 0;
+ width: 100%;
+ height: calc(100% / 3);
+ border-top-width: 1px;
+ border-bottom-width: 1px;
+}
+
+.cropper-dashed.dashed-v {
+ top: 0;
+ left: calc(100% / 3);
+ width: calc(100% / 3);
+ height: 100%;
+ border-right-width: 1px;
+ border-left-width: 1px;
+}
+
+.cropper-center {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ display: block;
+ width: 0;
+ height: 0;
+ opacity: 0.75;
+}
+
+.cropper-center::before,
+.cropper-center::after {
+ position: absolute;
+ display: block;
+ background-color: var(--background-subdued);
+ content: ' ';
+}
+
+.cropper-center::before {
+ top: 0;
+ left: -3px;
+ width: 7px;
+ height: 1px;
+}
+
+.cropper-center::after {
+ top: -3px;
+ left: 0;
+ width: 1px;
+ height: 7px;
+}
+
+.cropper-face,
+.cropper-line,
+.cropper-point {
+ position: absolute;
+ display: block;
+ width: 100%;
+ height: 100%;
+ opacity: 0.1;
+}
+
+.cropper-face {
+ top: 0;
+ left: 0;
+ background-color: var(--foreground-inverted);
+}
+
+.cropper-line {
+ background-color: #000;
+ opacity: 0.05;
+}
+
+.cropper-line.line-e {
+ top: 0;
+ right: -3px;
+ width: 5px;
+ cursor: ew-resize;
+}
+
+.cropper-line.line-n {
+ top: -3px;
+ left: 0;
+ height: 5px;
+ cursor: ns-resize;
+}
+
+.cropper-line.line-w {
+ top: 0;
+ left: -3px;
+ width: 5px;
+ cursor: ew-resize;
+}
+
+.cropper-line.line-s {
+ bottom: -3px;
+ left: 0;
+ height: 5px;
+ cursor: ns-resize;
+}
+
+.cropper-point {
+ width: 10px;
+ height: 10px;
+ background: #fff;
+ border-radius: 50%;
+ opacity: 1;
+}
+
+.cropper-point.point-e {
+ top: 50%;
+ right: -5px;
+ margin-top: -5px;
+ cursor: ew-resize;
+}
+
+.cropper-point.point-n {
+ top: -5px;
+ left: 50%;
+ margin-left: -5px;
+ cursor: ns-resize;
+}
+
+.cropper-point.point-w {
+ top: 50%;
+ left: -5px;
+ margin-top: -5px;
+ cursor: ew-resize;
+}
+
+.cropper-point.point-s {
+ bottom: -5px;
+ left: 50%;
+ margin-left: -5px;
+ cursor: s-resize;
+}
+
+.cropper-point.point-ne {
+ top: -5px;
+ right: -5px;
+ cursor: nesw-resize;
+}
+
+.cropper-point.point-nw {
+ top: -5px;
+ left: -5px;
+ cursor: nwse-resize;
+}
+
+.cropper-point.point-sw {
+ bottom: -5px;
+ left: -5px;
+ cursor: nesw-resize;
+}
+
+.cropper-point.point-se {
+ right: -5px;
+ bottom: -5px;
+ cursor: nwse-resize;
+}
+
+.cropper-point.point-se::before {
+ position: absolute;
+ right: -50%;
+ bottom: -50%;
+ display: block;
+ width: 200%;
+ height: 200%;
+ background-color: var(--primary);
+ opacity: 0;
+ content: ' ';
+}
+
+.cropper-invisible {
+ opacity: 0;
+}
+
+.cropper-bg {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
+}
+
+.cropper-hide {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+}
+
+.cropper-hidden {
+ display: none !important;
+}
+
+.cropper-move {
+ cursor: move;
+}
+
+.cropper-crop {
+ cursor: crosshair;
+}
+
+.cropper-disabled .cropper-drag-box,
+.cropper-disabled .cropper-face,
+.cropper-disabled .cropper-line,
+.cropper-disabled .cropper-point {
+ cursor: not-allowed;
+}
diff --git a/src/styles/main.scss b/src/styles/main.scss
index 5022ab423d..c3bbbb9271 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -7,6 +7,7 @@
@import 'themes/light';
@import 'lib/codemirror';
@import 'lib/portal-vue';
+@import 'lib/cropperjs';
body.light {
@include light;
diff --git a/src/views/private/components/image-editor/image-editor.vue b/src/views/private/components/image-editor/image-editor.vue
new file mode 100644
index 0000000000..32cc087cff
--- /dev/null
+++ b/src/views/private/components/image-editor/image-editor.vue
@@ -0,0 +1,366 @@
+
+
+
+
+
+
+
+
+
+
+
+ error
+
+
+
+
+
![]()
+
+
+
+
+
+
+ {{ $t('cancel') }}
+ {{ $t('save') }}
+
+
+
+
+
+
+
diff --git a/src/views/private/components/image-editor/index.ts b/src/views/private/components/image-editor/index.ts
new file mode 100644
index 0000000000..f97f64ff0a
--- /dev/null
+++ b/src/views/private/components/image-editor/index.ts
@@ -0,0 +1,4 @@
+import ImageEditor from './image-editor.vue';
+
+export { ImageEditor };
+export default ImageEditor;
diff --git a/yarn.lock b/yarn.lock
index c6674d0fc9..0486d2510b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4923,6 +4923,11 @@ create-react-context@0.3.0, create-react-context@^0.3.0:
gud "^1.0.0"
warning "^4.0.3"
+cropperjs@^1.5.6:
+ version "1.5.6"
+ resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.5.6.tgz#82faf432bec709d828f2f7a96d1179198edaf0e2"
+ integrity sha512-eAgWf4j7sNJIG329qUHIFi17PSV0VtuWyAu9glZSgu/KlQSrfTQOC2zAz+jHGa5fAB+bJldEnQwvJEaJ8zRf5A==
+
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"