Skip to content

Commit

Permalink
Add autosave
Browse files Browse the repository at this point in the history
  • Loading branch information
NiTrO0FuN committed Dec 5, 2023
1 parent d05d05f commit 5257ba6
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 54 deletions.
4 changes: 2 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<q-toolbar class="bg-secondary shadow-3 text-white">
<q-icon name="data_object" size="3em"/>
<q-toolbar-title>Easy E2</q-toolbar-title>
<q-select filled popup-content-class="qselectpopup bg-primary" dark style="margin:2px 15px;font-size:large;text-transform: uppercase;"
<q-select filled popup-content-class="qselectpopup bg-primary" dark style="margin:5px 15px;font-size:large;text-transform: uppercase;"
bg-color="primary" color="blue" v-model="$i18n.locale" :options="$i18n.availableLocales"/>
<whats-hot/>
<WhatsHot/>
</q-toolbar>
<router-view/>
</div>
Expand Down
66 changes: 63 additions & 3 deletions src/components/CreationZone.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</template>

<script>
import { mapState, mapWritableState } from 'pinia'
import { mapState, mapWritableState, mapActions } from 'pinia'
import { useScreensStore } from '@/stores/screensObjects'
import CanvaSwitcher from './EGPCreation/CanvaSwitcher.vue';
Expand All @@ -31,10 +31,11 @@ export default {
}
},
computed: {
...mapState(useScreensStore, ['screensObjects']),
...mapState(useScreensStore, ['screensObjects', 'objectsCount']),
...mapWritableState(useScreensStore, ['activeCanva'])
},
methods: {
...mapActions(useScreensStore, {resetScreenStore: '$reset' }),
prevCanva() {
if(this.activeCanva<=0) {return}
this.deselectShape()
Expand Down Expand Up @@ -90,10 +91,69 @@ export default {
},
refreshCode() {
this.screensObjects[this.activeCanva] = this.$refs.canva.canvas.getObjects()
}
},
saveToLocal() {
//Don't save if no changes
if (JSON.stringify(this.screensObjects) == localStorage.getItem("egpSave")) {return}
//Don't save if nothing to save
if (this.objectsCount == 0) {return}
localStorage.setItem("egpSave", JSON.stringify(this.screensObjects))
this.$q.notify({
color: "positive",
icon: "save",
position: "top-left",
timeout: 1000
})
},
loadFromLocal() {
if (!localStorage.getItem("egpSave")) {return}
let parsedScreens;
try {
parsedScreens = JSON.parse(localStorage.getItem("egpSave"))
} catch (error) {
this.$q.notify({
type: "negative",
message: this.$t("save.error_load")
})
localStorage.removeItem("egpSave")
return
}
if (this.selectedShape) {this.deselectShape()}
this.resetScreenStore()
parsedScreens.forEach(screen => {
let objects = []
screen.forEach(obj => {
let parsedObject = this.$refs.canva.createObject(obj)
this.$refs.canva.canvas.add(parsedObject)
objects.push(parsedObject)
});
this.screensObjects.push(objects)
});
this.$refs.canva.canvas._objects = this.screensObjects[this.activeCanva]
this.$refs.canva.refreshCanva()
this.$q.notify({
type: "positive",
message: this.$t("save.success_load")
})
},
},
mounted () {
this.refreshCode()
//Load previous save
if(localStorage.getItem("egpSave")) {
this.$q.notify({
color: "info",
message: this.$t("save.found"),
icon: "save",
progress: true,
progressClass: "saveProgress",
timeout: 10*1000, //10 sec to choose
actions: [{icon: "done", handler: this.loadFromLocal},
{icon: "close", color: "negative"}]
})
}
//Auto save every minute if needed
setInterval(this.saveToLocal, 1*60*1000)
},
components: { CanvaSwitcher, ShapeOrder, CanvaVue, ShapeEditor, ShapeCreator}
}
Expand Down
112 changes: 68 additions & 44 deletions src/components/EGPCreation/CanvaVue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,35 +61,79 @@
})
}
})
this.canvas.on("object:scaling", function(o) {
let t = o.target
t.top = Math.round(t.top);
t.left = Math.round(t.left);
})
},
methods: {
createObject(options) {
let object;
if (options.type == "rect") {
object = new fabric.Rect(options)
} else if (options.type == "ellipse") {
object = new fabric.Ellipse(options)
} else if (options.type == "polygon") {
object = new fabric.Polygon(options.points, options)
} else if (options.type == "i-text") {
object = new fabric.IText(options.text, options)
}
object.toObject = function() {
return fabric.util.object.extend(object.toObject.call(this), {
...(this.actions? {actions: this.actions}: {}),
filled: this.filled,
hasControls: this.hasControls,
});
};
let self = this
object.on("selected", function() {
object.top = Math.round(object.top);
object.left = Math.round(object.left);
self.$emit("shape-selected",object)
})
object = reactive(object)
this.$watch(() => object.filled, function() {
if(!object.filled) {
object.set("stroke",object.fill)
object.set("fill","rgba(0,0,0,0)")
} else {
object.set("fill", object.stroke)
object.set("stroke", null)
}
this.refreshCanva()
})
return object
},
addObject(objectType) {
if(this.canvas.getObjects().length>=300){return}
var object
if(objectType=="rectangle") {
object = new fabric.Rect({
top:256,left:256,width:100,height:100,
originX:'center',originY:'center',
fill:'rgba(255,255,255,1)',
strokeWidth: 3,
filled: true,
actions: []
})
object = this.createObject({
type: "rect",
top: 256, left: 256, width: 100, height: 100,
originX:'center',originY:'center',
fill:'rgba(255,255,255,1)',
strokeWidth: 3,
filled: true,
actions: []
})
} else if(objectType=="circle") {
object = new fabric.Ellipse({
top:256,left:256,rx:50,ry:50,
originX:'center',originY:'center',
fill:"rgba(255,255,255,1)",
strokeWidth: 3,
filled:true,
actions: []
})
object = this.createObject({
type: "ellipse",
top: 256, left: 256, rx: 50, ry: 50,
originX:'center',originY:'center',
fill:"rgba(255,255,255,1)",
strokeWidth: 3,
filled:true,
actions: []
})
} else if(objectType=="triangle") {
object = new fabric.Polygon([
{ x: 70, y: 0},
object = this.createObject({
type: "polygon",
points: [{ x: 70, y: 0},
{ x: 0, y: 120},
{ x: 140, y: 120},
],{
{ x: 140, y: 120}],
fill:'rgba(255,255,255,1)',
strokeWidth: 3,
filled:true,
Expand All @@ -98,7 +142,9 @@
actions: []
})
} else if(objectType=="text") {
object = new fabric.IText("EGP", {
object = this.createObject({
type: "i-text",
text: "EGP",
top: 0, left:0,
fill: 'rgba(255,255,255,1)',
filled: true,
Expand All @@ -108,29 +154,7 @@
hasControls: false,
}
)
}
let self = this
object.on("selected", function() {
object.top = Math.round(object.top);
object.left = Math.round(object.left);
self.$emit("shape-selected",object)
})
object.on("scaling", function() {
object.top = Math.round(object.top);
object.left = Math.round(object.left);
})
object = reactive(object)
this.$watch(() => object.filled, function() {
if(!object.filled) {
object.set("stroke",object.fill)
object.set("fill","rgba(0,0,0,0)")
} else {
object.set("fill", object.stroke)
object.set("stroke", null)
}
this.refreshCanva()
})
}
this.canvas.add(object)
this.updateObjectList()
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/EGPCreation/ShapeCreator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="column justify-center">
<div class="column addcolumn">
<q-btn v-for="shape in shapes" round color="orange" :icon="shape.icon" @click="this.$emit('add-shape',shape)">
<q-tooltip class="bg-secondary text-body1">{{this.$t(shape.name)}}</q-tooltip>
<q-tooltip class="bg-secondary text-body1">{{$t(shape.name)}}</q-tooltip>
</q-btn>
<q-btn v-if="selectedShape" round class="" color="negative" icon="delete" @click="this.$emit('remove-shape')"/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/EGPCreation/ShapeOrder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
<div class="column justify-center">
<div class="column addcolumn">
<q-btn v-for="button in buttons" round color="positive" :icon="button.icon" @click="this.$emit('move',button.name)">
<q-tooltip class="bg-secondary text-body2">{{this.$t("editor."+button.name)}}</q-tooltip>
<q-tooltip class="bg-secondary text-body2">{{$t("editor."+button.name)}}</q-tooltip>
</q-btn>
<q-btn round color="grey" icon="do_not_touch" @click="this.$emit('unselect-shape')">
<q-tooltip class="bg-secondary text-body2">{{this.$t("editor.unselect")}}</q-tooltip>
<q-tooltip class="bg-secondary text-body2">{{$t("editor.unselect")}}</q-tooltip>
</q-btn>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/WhatsHot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
data() {
return {
features: [
{feature:"f2",isNew:false},
{feature:"f3",isNew:false},
{feature:"f4",isNew:true},
{feature:"f4",isNew:false},
{feature:"f5",isNew:true},
{feature:"f6",isNew:true},
]
}
},
Expand Down
12 changes: 12 additions & 0 deletions src/localisation/loc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default {
f3: "Add text",
f4: "Multiple screens",
f5: "Add actions",
f6: "Automatic backups",
},
code_shower: {
generated_code: "Generated code",
Expand Down Expand Up @@ -63,6 +64,11 @@ export default {
thickness: "Epaisseur",
color: "Color",
fill: "Fill",
save : {
found: "A previous save was found, would you like to load it?",
error_load: "An error happened loading the previous save.",
success_load: "The previous save has been loaded successfully."
},
},
fr: {
features : {
Expand All @@ -72,6 +78,7 @@ export default {
f3: "Ajouter du texte",
f4: "Écrans multiples",
f5: "Ajouter des actions",
f6: "Sauvegardes automatiques",
},
code_shower: {
generated_code: "Code généré",
Expand Down Expand Up @@ -128,5 +135,10 @@ export default {
thickness: "Epaisseur",
color: "Couleur",
fill: "Remplir",
save : {
found: "Une sauvegarde a été trouvée, voulez vous l'utiliser?",
error_load: "Une erreur est survenue lors du chargement de la précédente sauvegarde.",
success_load: "La sauvegarde a été chargée avec succès."
},
}
}
9 changes: 9 additions & 0 deletions src/stores/screensObjects.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,13 @@ export const useScreensStore = defineStore('screensObjects', {
screensObjects: [],
activeCanva: 0,
}),
getters: {
objectsCount: (state) => {
let count = 0
state.screensObjects.forEach(screen => {
count += screen.length
});
return count
}
}
})

0 comments on commit 5257ba6

Please sign in to comment.