mirror of
https://github.com/penpot/penpot.git
synced 2025-02-18 21:06:11 -05:00
✨ Visual redesign for undo history
This commit is contained in:
parent
0e3c3ebfbd
commit
b8e47c87ba
4 changed files with 637 additions and 97 deletions
|
@ -1441,7 +1441,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settings.multiple" : {
|
"settings.multiple" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/stroke.cljs:156" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/stroke.cljs:147" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Mixed",
|
"en" : "Mixed",
|
||||||
"fr" : null,
|
"fr" : null,
|
||||||
|
@ -1666,7 +1666,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.assets" : {
|
"workspace.assets.assets" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:629" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:628" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Assets",
|
"en" : "Assets",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1675,7 +1675,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.box-filter-all" : {
|
"workspace.assets.box-filter-all" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:649" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:648" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "All assets",
|
"en" : "All assets",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1702,7 +1702,7 @@
|
||||||
"unused" : true
|
"unused" : true
|
||||||
},
|
},
|
||||||
"workspace.assets.colors" : {
|
"workspace.assets.colors" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:329", "src/app/main/ui/workspace/sidebar/assets.cljs:652" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:329", "src/app/main/ui/workspace/sidebar/assets.cljs:651" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Colors",
|
"en" : "Colors",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1711,7 +1711,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.components" : {
|
"workspace.assets.components" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:83", "src/app/main/ui/workspace/sidebar/assets.cljs:650" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:83", "src/app/main/ui/workspace/sidebar/assets.cljs:649" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Components",
|
"en" : "Components",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1738,7 +1738,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.file-library" : {
|
"workspace.assets.file-library" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:532" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:531" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "File library",
|
"en" : "File library",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1747,7 +1747,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.graphics" : {
|
"workspace.assets.graphics" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:164", "src/app/main/ui/workspace/sidebar/assets.cljs:651" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:164", "src/app/main/ui/workspace/sidebar/assets.cljs:650" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Graphics",
|
"en" : "Graphics",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1756,7 +1756,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.libraries" : {
|
"workspace.assets.libraries" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:632" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:631" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Libraries",
|
"en" : "Libraries",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1765,7 +1765,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.not-found" : {
|
"workspace.assets.not-found" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:593" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:592" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "No assets found",
|
"en" : "No assets found",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1783,7 +1783,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.search" : {
|
"workspace.assets.search" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:636" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:635" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Search assets",
|
"en" : "Search assets",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1792,7 +1792,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.shared" : {
|
"workspace.assets.shared" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:534" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:533" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "SHARED",
|
"en" : "SHARED",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -1801,7 +1801,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.assets.typography" : {
|
"workspace.assets.typography" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:420", "src/app/main/ui/workspace/sidebar/assets.cljs:653" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:420", "src/app/main/ui/workspace/sidebar/assets.cljs:652" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Typographies"
|
"en" : "Typographies"
|
||||||
}
|
}
|
||||||
|
@ -1855,13 +1855,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.gradients.linear" : {
|
"workspace.gradients.linear" : {
|
||||||
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:39", "src/app/main/ui/components/color_bullet.cljs:30" ],
|
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:39", "src/app/main/ui/components/color_bullet.cljs:31" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Linear gradient"
|
"en" : "Linear gradient"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.gradients.radial" : {
|
"workspace.gradients.radial" : {
|
||||||
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:40", "src/app/main/ui/components/color_bullet.cljs:31" ],
|
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:40", "src/app/main/ui/components/color_bullet.cljs:32" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Radial gradient"
|
"en" : "Radial gradient"
|
||||||
}
|
}
|
||||||
|
@ -2044,19 +2044,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.colors.big-thumbnails" : {
|
"workspace.libraries.colors.big-thumbnails" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:171" ],
|
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:169" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Big thumbnails"
|
"en" : "Big thumbnails"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.colors.file-library" : {
|
"workspace.libraries.colors.file-library" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/colorpicker/libraries.cljs:87", "src/app/main/ui/workspace/colorpalette.cljs:149" ],
|
"used-in" : [ "src/app/main/ui/workspace/colorpicker/libraries.cljs:87", "src/app/main/ui/workspace/colorpalette.cljs:147" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "File library"
|
"en" : "File library"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.colors.recent-colors" : {
|
"workspace.libraries.colors.recent-colors" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/colorpicker/libraries.cljs:86", "src/app/main/ui/workspace/colorpalette.cljs:159" ],
|
"used-in" : [ "src/app/main/ui/workspace/colorpicker/libraries.cljs:86", "src/app/main/ui/workspace/colorpalette.cljs:157" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Recent colors"
|
"en" : "Recent colors"
|
||||||
}
|
}
|
||||||
|
@ -2068,7 +2068,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.colors.small-thumbnails" : {
|
"workspace.libraries.colors.small-thumbnails" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:176" ],
|
"used-in" : [ "src/app/main/ui/workspace/colorpalette.cljs:174" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Small thumbnails"
|
"en" : "Small thumbnails"
|
||||||
}
|
}
|
||||||
|
@ -2173,13 +2173,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.text.multiple-typography" : {
|
"workspace.libraries.text.multiple-typography" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:266" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:267" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Multiple typographies"
|
"en" : "Multiple typographies"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.libraries.text.multiple-typography-tooltip" : {
|
"workspace.libraries.text.multiple-typography-tooltip" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:268" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:269" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Unlink all typographies"
|
"en" : "Unlink all typographies"
|
||||||
}
|
}
|
||||||
|
@ -2302,7 +2302,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.fill" : {
|
"workspace.options.fill" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:54" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:53" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Fill",
|
"en" : "Fill",
|
||||||
"fr" : "Remplissage",
|
"fr" : "Remplissage",
|
||||||
|
@ -2500,7 +2500,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.group-fill" : {
|
"workspace.options.group-fill" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:53" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:52" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Group fill",
|
"en" : "Group fill",
|
||||||
"fr" : null,
|
"fr" : null,
|
||||||
|
@ -2509,7 +2509,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.group-stroke" : {
|
"workspace.options.group-stroke" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:72" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:63" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Group stroke",
|
"en" : "Group stroke",
|
||||||
"fr" : null,
|
"fr" : null,
|
||||||
|
@ -2590,7 +2590,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.selection-fill" : {
|
"workspace.options.selection-fill" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:52" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/fill.cljs:51" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Selection fill",
|
"en" : "Selection fill",
|
||||||
"fr" : null,
|
"fr" : null,
|
||||||
|
@ -2599,7 +2599,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.selection-stroke" : {
|
"workspace.options.selection-stroke" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:71" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:62" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Selection stroke",
|
"en" : "Selection stroke",
|
||||||
"fr" : null,
|
"fr" : null,
|
||||||
|
@ -2668,7 +2668,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke" : {
|
"workspace.options.stroke" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:73" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:64" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Stroke",
|
"en" : "Stroke",
|
||||||
"fr" : "Bordure",
|
"fr" : "Bordure",
|
||||||
|
@ -2677,7 +2677,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.center" : {
|
"workspace.options.stroke.center" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:163" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:154" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Center",
|
"en" : "Center",
|
||||||
"fr" : "Centre",
|
"fr" : "Centre",
|
||||||
|
@ -2686,7 +2686,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.dashed" : {
|
"workspace.options.stroke.dashed" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:173" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:164" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Dashed",
|
"en" : "Dashed",
|
||||||
"fr" : "Tiré",
|
"fr" : "Tiré",
|
||||||
|
@ -2695,7 +2695,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.dotted" : {
|
"workspace.options.stroke.dotted" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:172" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:163" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Dotted",
|
"en" : "Dotted",
|
||||||
"fr" : "Pointillé",
|
"fr" : "Pointillé",
|
||||||
|
@ -2704,7 +2704,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.inner" : {
|
"workspace.options.stroke.inner" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:164" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:155" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Inside",
|
"en" : "Inside",
|
||||||
"fr" : "Intérieur",
|
"fr" : "Intérieur",
|
||||||
|
@ -2713,7 +2713,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.mixed" : {
|
"workspace.options.stroke.mixed" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:174" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:165" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Mixed",
|
"en" : "Mixed",
|
||||||
"fr" : "Mixte",
|
"fr" : "Mixte",
|
||||||
|
@ -2722,7 +2722,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.outer" : {
|
"workspace.options.stroke.outer" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:165" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:156" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Outside",
|
"en" : "Outside",
|
||||||
"fr" : "Extérieur",
|
"fr" : "Extérieur",
|
||||||
|
@ -2731,7 +2731,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.options.stroke.solid" : {
|
"workspace.options.stroke.solid" : {
|
||||||
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:171" ],
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:162" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Solid",
|
"en" : "Solid",
|
||||||
"fr" : "Solide",
|
"fr" : "Solide",
|
||||||
|
@ -3070,8 +3070,230 @@
|
||||||
"es" : "Texto (T)"
|
"es" : "Texto (T)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"workspace.undo.empty" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:272" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "There are no history changes so far"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.delete" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:110" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "Deleted %s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.modify" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:109" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "Modified %s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.move" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:111" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "Moved objects"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.circle" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "circles"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.color" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "color assets"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.component" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "components"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.curve" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "curves"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.frame" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "artboard"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.group" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "groups"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.image" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "images"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.media" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "graphic assets"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.multiple" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "objects"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.page" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "pages"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.path" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "paths"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.rect" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "rectangles"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.shape" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "shapes"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.text" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "texts"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.multiple.typography" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "typography assets"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.new" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:108" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "New %s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.circle" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "circle"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.color" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "color asset"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.component" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "component"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.curve" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "curve"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.frame" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "frame"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.group" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "group"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.image" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "image"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.media" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "graphic asset"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.multiple" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "object"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.page" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "page"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.path" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "path"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.rect" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "rectangle"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.shape" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "shape"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.text" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "text"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.single.typography" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : "typography asset"
|
||||||
|
},
|
||||||
|
"unused" : true
|
||||||
|
},
|
||||||
|
"workspace.undo.entry.unknown" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:112" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "Operation over %s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace.undo.title" : {
|
||||||
|
"used-in" : [ "src/app/main/ui/workspace/sidebar/history.cljs:268" ],
|
||||||
|
"translations" : {
|
||||||
|
"en" : "History"
|
||||||
|
}
|
||||||
|
},
|
||||||
"workspace.updates.dismiss" : {
|
"workspace.updates.dismiss" : {
|
||||||
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:538" ],
|
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:542" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Dismiss",
|
"en" : "Dismiss",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -3080,7 +3302,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.updates.there-are-updates" : {
|
"workspace.updates.there-are-updates" : {
|
||||||
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:534" ],
|
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:538" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "There are updates in shared libraries",
|
"en" : "There are updates in shared libraries",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
@ -3089,7 +3311,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspace.updates.update" : {
|
"workspace.updates.update" : {
|
||||||
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:536" ],
|
"used-in" : [ "src/app/main/data/workspace/libraries.cljs:540" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
"en" : "Update",
|
"en" : "Update",
|
||||||
"fr" : "",
|
"fr" : "",
|
||||||
|
|
|
@ -8,37 +8,122 @@
|
||||||
// Copyright (c) 2020 UXBOX Labs SL
|
// Copyright (c) 2020 UXBOX Labs SL
|
||||||
|
|
||||||
.history-toolbox {
|
.history-toolbox {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-toolbox-title {
|
.history-toolbox-title {
|
||||||
color: $color-gray-10;
|
color: $color-gray-10;
|
||||||
font-size: $fs14;
|
font-size: $fs14;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.undo-history {
|
.history-entry-empty {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.history-entry-empty-icon {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
fill: $color-gray-40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-empty-msg {
|
||||||
|
color: $color-gray-30;
|
||||||
font-size: $fs12;
|
font-size: $fs12;
|
||||||
color: $color-gray-10;
|
}
|
||||||
|
}
|
||||||
.undo-entry {
|
|
||||||
max-height: 10rem;
|
.history-entries {
|
||||||
overflow: auto;
|
font-size: $fs12;
|
||||||
margin: 0.5rem;
|
color: $color-gray-20;
|
||||||
|
fill: $color-gray-20;
|
||||||
&.transaction {
|
}
|
||||||
border: 2px solid $color-primary;
|
|
||||||
}
|
.history-entry {
|
||||||
}
|
border: 1px solid $color-gray-60;
|
||||||
|
border-radius: 4px;
|
||||||
.undo-entry-change {
|
margin: 0.5rem;
|
||||||
background-color: #1F1F1F;
|
display: flex;
|
||||||
padding: 0.5rem;
|
flex-direction: column;
|
||||||
}
|
padding: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
.separator {
|
|
||||||
margin: 0.5rem;
|
transition: border 0.2s;
|
||||||
border-color: $color-primary;
|
|
||||||
}
|
&.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.current {
|
||||||
|
background-color: $color-gray-60;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hover {
|
||||||
|
border-color: $color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-summary {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
* {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-summary-icon {
|
||||||
|
svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-summary-text {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-summary-button {
|
||||||
|
opacity: 0;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-detail &,
|
||||||
|
.hover & {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-detail & {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-detail {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.show-detail & {
|
||||||
|
display: block;
|
||||||
|
padding: 1rem 0 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-entry-details-list {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,10 @@
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:parent-id parent-id
|
:parent-id parent-id
|
||||||
:shapes shapes
|
:shapes shapes
|
||||||
:index index-in-parent}]
|
:index index-in-parent}
|
||||||
|
{:type :del-obj
|
||||||
|
:page-id page-id
|
||||||
|
:id (:id group)}]
|
||||||
uchanges [{:type :add-obj
|
uchanges [{:type :add-obj
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:id (:id group)
|
:id (:id group)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[app.common.data :as d]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.data.history :as udh]
|
[app.main.data.history :as udh]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -27,42 +28,271 @@
|
||||||
(def workspace-undo
|
(def workspace-undo
|
||||||
(l/derived :workspace-undo st/state))
|
(l/derived :workspace-undo st/state))
|
||||||
|
|
||||||
(mf/defc undo-entry [{:keys [index entry objects is-transaction?] :or {is-transaction? false}}]
|
(defn get-object
|
||||||
(let [{:keys [redo-changes]} entry]
|
"Searchs for a shape inside the objects list or inside the undo history"
|
||||||
[:li.undo-entry {:class (when is-transaction? "transaction")}
|
[id entries objects]
|
||||||
(for [[idx-change {:keys [type id operations]}] (map-indexed vector redo-changes)]
|
(let [search-deleted-shape
|
||||||
[:div.undo-entry-change {:key (str "change-" idx-change)}
|
(fn [id entries]
|
||||||
[:div.undo-entry-change-data (when type (str type)) " " (when id (str (get-in objects [id :name] (subs (str id) 0 8))))]
|
(let [search-obj (fn [obj] (and (= (:type obj) :add-obj)
|
||||||
(when operations
|
(= (:id obj) id)))
|
||||||
[:div.undo-entry-change-data (str/join ", "
|
search-delete-entry (fn [{:keys [undo-changes redo-changes]}]
|
||||||
(map (comp name :attr)
|
(or (d/seek search-obj undo-changes)
|
||||||
(filter #(= (:type %) :set) operations)))])])]))
|
(d/seek search-obj redo-changes)))
|
||||||
|
{:keys [obj]} (->> entries (d/seek search-delete-entry) search-delete-entry)]
|
||||||
|
obj))]
|
||||||
|
(or (get objects id)
|
||||||
|
(search-deleted-shape id entries))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn extract-operation
|
||||||
|
"Generalizes the type of operation for different types of change"
|
||||||
|
[change]
|
||||||
|
(case (:type change)
|
||||||
|
(:add-obj :add-page :add-color :add-media :add-component :add-typography) :new
|
||||||
|
(:mod-obj :mod-page :mod-color :mod-media :mod-component :mod-typography) :modify
|
||||||
|
(:del-obj :del-page :del-color :del-media :del-component :del-typography) :delete
|
||||||
|
:mov-objects :move
|
||||||
|
nil))
|
||||||
|
|
||||||
|
(defn parse-change
|
||||||
|
"Given a single change parses the information into an uniform map"
|
||||||
|
[change]
|
||||||
|
(let [r (fn [type id]
|
||||||
|
{:type type
|
||||||
|
:operation (extract-operation change)
|
||||||
|
:detail (:operations change)
|
||||||
|
:id (cond
|
||||||
|
(and (coll? id) (= 1 (count id))) (first id)
|
||||||
|
(coll? id) :multiple
|
||||||
|
:else id)})]
|
||||||
|
(case (:type change)
|
||||||
|
:set-option (r :page (:page-id change))
|
||||||
|
(:add-obj
|
||||||
|
:mod-obj
|
||||||
|
:del-obj) (r :shape (:id change))
|
||||||
|
:reg-objects nil
|
||||||
|
:mov-objects (r :shape (:shapes change))
|
||||||
|
(:add-page
|
||||||
|
:mod-page :del-page
|
||||||
|
:mov-page) (r :page (:id change))
|
||||||
|
(:add-color
|
||||||
|
:mod-color) (r :color (get-in change [:color :id]))
|
||||||
|
:del-color (r :color (:id change))
|
||||||
|
:add-recent-color nil
|
||||||
|
(:add-media
|
||||||
|
:mod-media) (r :media (get-in change [:object :id]))
|
||||||
|
:del-media (r :media (:id change))
|
||||||
|
(:add-component
|
||||||
|
:mod-component
|
||||||
|
:del-component) (r :component (:id change))
|
||||||
|
(:add-typography
|
||||||
|
:mod-typography) (r :typography (get-in change [:typography :id]))
|
||||||
|
:del-typography (r :typography (:id change))
|
||||||
|
nil)))
|
||||||
|
|
||||||
|
(defn resolve-shape-types
|
||||||
|
"Retrieve the type to be shown to the user"
|
||||||
|
[entries objects]
|
||||||
|
(let [resolve-type (fn [{:keys [type id]}]
|
||||||
|
(if (or (not= type :shape) (= id :multiple))
|
||||||
|
type
|
||||||
|
(:type (get-object id entries objects))))
|
||||||
|
|
||||||
|
map-fn (fn [entry]
|
||||||
|
(if (and (= (:type entry) :shape)
|
||||||
|
(not= (:id entry) :multiple))
|
||||||
|
(assoc entry :type (resolve-type entry))
|
||||||
|
entry))]
|
||||||
|
(fn [entries]
|
||||||
|
(map map-fn entries))))
|
||||||
|
|
||||||
|
(defn entry-type->message
|
||||||
|
"Formats the message that will be displayed to the user"
|
||||||
|
[locale type multiple?]
|
||||||
|
(let [arity (if multiple? "multiple" "single")
|
||||||
|
attribute (name (or type :multiple))]
|
||||||
|
(t locale (str/format "workspace.undo.entry.%s.%s" arity attribute))))
|
||||||
|
|
||||||
|
(defn entry->message [locale entry]
|
||||||
|
(let [value (entry-type->message locale (:type entry) (= :multiple (:id entry)))]
|
||||||
|
(case (:operation entry)
|
||||||
|
:new (t locale "workspace.undo.entry.new" value)
|
||||||
|
:modify (t locale "workspace.undo.entry.modify" value)
|
||||||
|
:delete (t locale "workspace.undo.entry.delete" value)
|
||||||
|
:move (t locale "workspace.undo.entry.move" value)
|
||||||
|
(t locale "workspace.undo.entry.unknown" value))))
|
||||||
|
|
||||||
|
(defn entry->icon [{:keys [type]}]
|
||||||
|
(case type
|
||||||
|
:page i/file-html
|
||||||
|
:shape i/layers
|
||||||
|
:rect i/box
|
||||||
|
:circle i/circle
|
||||||
|
:text i/text
|
||||||
|
:curve i/curve
|
||||||
|
:path i/curve
|
||||||
|
:frame i/artboard
|
||||||
|
:group i/folder
|
||||||
|
:color i/palette
|
||||||
|
:typography i/titlecase
|
||||||
|
:component i/component
|
||||||
|
:media i/image
|
||||||
|
:image i/image
|
||||||
|
i/layers))
|
||||||
|
|
||||||
|
(defn is-shape? [type]
|
||||||
|
#{:shape :rect :circle :text :curve :path :frame :group})
|
||||||
|
|
||||||
|
(defn parse-entry [{:keys [redo-changes]}]
|
||||||
|
(->> redo-changes
|
||||||
|
(map parse-change)))
|
||||||
|
|
||||||
|
(defn safe-name [maybe-keyword]
|
||||||
|
(if (keyword? maybe-keyword)
|
||||||
|
(name maybe-keyword)
|
||||||
|
maybe-keyword))
|
||||||
|
|
||||||
|
(defn select-entry
|
||||||
|
"Selects the entry the user will see inside a list of posible entries.
|
||||||
|
Sometimes the result will be a combination."
|
||||||
|
[candidates]
|
||||||
|
(let [;; Group by id and type
|
||||||
|
entries (->> candidates
|
||||||
|
(remove nil?)
|
||||||
|
(group-by #(vector (:type %) (:operation %) (:id %)) ))
|
||||||
|
|
||||||
|
single? (fn [coll] (= (count coll) 1))
|
||||||
|
|
||||||
|
;; Retrieve also by-type and by-operation
|
||||||
|
types (group-by first (keys entries))
|
||||||
|
operations (group-by second (keys entries))
|
||||||
|
|
||||||
|
;; The cases for the selection of the representative entry are a bit
|
||||||
|
;; convoluted. Best to read the comments to clarify.
|
||||||
|
;; At this stage we have cleaned the entries but we can have a batch
|
||||||
|
;; of operations for a single undo-entry. We want to select the
|
||||||
|
;; one that is most interesting for the user.
|
||||||
|
selected-entry
|
||||||
|
(cond
|
||||||
|
;; If we only have one operation over one shape we return the last change
|
||||||
|
(single? entries)
|
||||||
|
(-> entries (get (first (keys entries))) (last))
|
||||||
|
|
||||||
|
;; If we're creating an object it will have priority
|
||||||
|
(single? (:new operations))
|
||||||
|
(-> entries (get (first (:new operations))) (last))
|
||||||
|
|
||||||
|
;; If there is only a deletion of 1 group we retrieve this operation because
|
||||||
|
;; the others will be the children
|
||||||
|
(single? (filter #(= :group (first %)) (:delete operations)))
|
||||||
|
(-> entries (get (first (filter #(= :group (first %)) (:delete operations)))) (last))
|
||||||
|
|
||||||
|
;; Otherwise we could have the same operation between several
|
||||||
|
;; types (i.e: delete various shapes). If that happens we return
|
||||||
|
;; the operation with `:multiple` id
|
||||||
|
(single? operations)
|
||||||
|
{:type (if (every? is-shape? (keys types)) :shape :multiple)
|
||||||
|
:id :multiple
|
||||||
|
:operation (first (keys operations))}
|
||||||
|
|
||||||
|
;; Finally, if we have several operations over several shapes we return
|
||||||
|
;; `:multiple` for operation and type and join the last of the operations for
|
||||||
|
;; each shape
|
||||||
|
:else
|
||||||
|
{:type :multiple
|
||||||
|
:id :multiple
|
||||||
|
:operation :multiple})
|
||||||
|
|
||||||
|
|
||||||
|
;; We add to the detail the information depending on the type of operation
|
||||||
|
detail
|
||||||
|
(case (:operation selected-entry)
|
||||||
|
:new (:id selected-entry)
|
||||||
|
:modify (->> candidates
|
||||||
|
(filter #(= :modify (:operation %)))
|
||||||
|
(group-by :id)
|
||||||
|
(d/mapm (fn [k v] (->> v
|
||||||
|
(mapcat :detail)
|
||||||
|
(map (comp safe-name :attr))
|
||||||
|
(remove nil?)
|
||||||
|
(into #{})))))
|
||||||
|
:delete (->> candidates
|
||||||
|
(filter #(= :delete (:operation %)))
|
||||||
|
(map :id))
|
||||||
|
candidates)]
|
||||||
|
|
||||||
|
(assoc selected-entry :detail detail)))
|
||||||
|
|
||||||
|
(defn parse-entries [entries objects]
|
||||||
|
(->> entries
|
||||||
|
(map parse-entry)
|
||||||
|
(map (resolve-shape-types entries objects))
|
||||||
|
(mapv select-entry)))
|
||||||
|
|
||||||
|
(mf/defc history-entry-details [{:keys [entry]}]
|
||||||
|
(let [{entries :items} (mf/deref workspace-undo)
|
||||||
|
objects (mf/deref refs/workspace-page-objects)]
|
||||||
|
|
||||||
|
[:div.history-entry-detail
|
||||||
|
(case (:operation entry)
|
||||||
|
:new
|
||||||
|
(:name (get-object (:detail entry) entries objects))
|
||||||
|
|
||||||
|
:delete
|
||||||
|
[:ul.history-entry-details-list
|
||||||
|
(for [id (:detail entry)]
|
||||||
|
(let [shape-name (:name (get-object id entries objects))]
|
||||||
|
[:li {:key id} shape-name]))]
|
||||||
|
|
||||||
|
|
||||||
|
:modify
|
||||||
|
[:ul.history-entry-details-list
|
||||||
|
(for [[id attributes] (:detail entry)]
|
||||||
|
(let [shape-name (:name (get-object id entries objects))]
|
||||||
|
[:li {:key id}
|
||||||
|
[:div shape-name]
|
||||||
|
[:div (str/join ", " attributes)]]))]
|
||||||
|
|
||||||
|
nil)]))
|
||||||
|
|
||||||
|
(mf/defc history-entry [{:keys [locale entry disabled? current?]}]
|
||||||
|
(let [hover? (mf/use-state false)
|
||||||
|
show-detail? (mf/use-state false)]
|
||||||
|
[:div.history-entry {:class (dom/classnames
|
||||||
|
:disabled disabled?
|
||||||
|
:current current?
|
||||||
|
:hover @hover?
|
||||||
|
:show-detail @show-detail?)
|
||||||
|
:on-mouse-enter #(reset! hover? true)
|
||||||
|
:on-mouse-leave #(reset! hover? false)
|
||||||
|
:on-click #(when (:detail entry)
|
||||||
|
(swap! show-detail? not))
|
||||||
|
}
|
||||||
|
[:div.history-entry-summary
|
||||||
|
[:div.history-entry-summary-icon (entry->icon entry)]
|
||||||
|
[:div.history-entry-summary-text (entry->message locale entry)]
|
||||||
|
(when (:detail entry)
|
||||||
|
[:div.history-entry-summary-button i/arrow-slide])]
|
||||||
|
|
||||||
|
(when show-detail?
|
||||||
|
[:& history-entry-details {:entry entry}])]))
|
||||||
|
|
||||||
(mf/defc history-toolbox []
|
(mf/defc history-toolbox []
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [locale (mf/deref i18n/locale)
|
||||||
|
objects (mf/deref refs/workspace-page-objects)
|
||||||
{:keys [items index transaction]} (mf/deref workspace-undo)
|
{:keys [items index transaction]} (mf/deref workspace-undo)
|
||||||
objects (mf/deref refs/workspace-page-objects)]
|
entries (parse-entries items objects)]
|
||||||
[:div.history-toolbox
|
[:div.history-toolbox
|
||||||
[:div.history-toolbox-title "History"]
|
[:div.history-toolbox-title (t locale "workspace.undo.title")]
|
||||||
[:ul.undo-history
|
(if (empty? entries)
|
||||||
[:*
|
[:div.history-entry-empty
|
||||||
(when (and
|
[:div.history-entry-empty-icon i/undo-history]
|
||||||
(> (count items) 0)
|
[:div.history-entry-empty-msg (t locale "workspace.undo.empty")]]
|
||||||
(or (nil? index)
|
[:ul.history-entries
|
||||||
(>= index (count items))))
|
(for [[idx-entry entry] (->> entries (map-indexed vector) reverse)] #_[i (range 0 10)]
|
||||||
[:hr.separator])
|
[:& history-entry {:key (str "entry-" idx-entry)
|
||||||
|
:locale locale
|
||||||
(when transaction
|
:entry entry
|
||||||
[:& undo-entry {:key (str "transaction")
|
:current? (= idx-entry index)
|
||||||
:objects objects
|
:disabled? (> idx-entry index)}])])]))
|
||||||
:is-transaction? true
|
|
||||||
:entry transaction}])
|
|
||||||
|
|
||||||
(for [[idx-entry entry] (->> items (map-indexed vector) reverse)]
|
|
||||||
[:*
|
|
||||||
(when (= index idx-entry) [:hr.separator {:data-index index}])
|
|
||||||
[:& undo-entry {:key (str "entry-" idx-entry)
|
|
||||||
:objects objects
|
|
||||||
:entry entry}]])
|
|
||||||
(when (= index -1) [:hr.separator])]]]))
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue