Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue-294] Ajout du niveau groupe dans l'arborescence #330

Merged
merged 53 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
124ccce
modify the drag n drop and groups layer in themes
LPoin Nov 15, 2024
a86d7e0
wip enregistrement groupes
LPoin Nov 18, 2024
50bf662
add save and load theme, groups and layers
LPoin Nov 22, 2024
a9cd59f
clean code
LPoin Nov 22, 2024
9e20c59
clean code and graphic design
LPoin Nov 22, 2024
2bffc43
modifie le title en name dans les groupes
LPoin Nov 26, 2024
09e01ad
display groups panel depending on whether or not a group is present
LPoin Nov 27, 2024
b8e6d5a
Modify button title for add theme, groups and layers
LPoin Nov 27, 2024
3dca0ca
issue 294 - clean delete layer in a group
LPoin Nov 28, 2024
2ce63c1
issue 294 - layer edition in a group && save studio at save editing l…
LPoin Nov 28, 2024
3321edb
modify the drag n drop and groups layer in themes
LPoin Nov 15, 2024
058e979
wip enregistrement groupes
LPoin Nov 18, 2024
5d2ec0a
add save and load theme, groups and layers
LPoin Nov 22, 2024
fa72b70
clean code
LPoin Nov 22, 2024
395d9aa
clean code and graphic design
LPoin Nov 22, 2024
68049eb
modifie le title en name dans les groupes
LPoin Nov 26, 2024
ef4395d
display groups panel depending on whether or not a group is present
LPoin Nov 27, 2024
28bb54d
Modify button title for add theme, groups and layers
LPoin Nov 27, 2024
39ada38
issue 294 - clean delete layer in a group
LPoin Nov 28, 2024
658a693
issue 294 - layer edition in a group && save studio at save editing l…
LPoin Nov 28, 2024
7b52fa0
rebase and clean
Gaetanbrl Nov 29, 2024
39473ea
Add vscode debug files
Gaetanbrl Nov 29, 2024
816ce2b
standardize code
Gaetanbrl Nov 29, 2024
b9ae420
translate comments
Gaetanbrl Nov 29, 2024
22b2b84
Merge pull request #38 from jdev-org/issue-294-gb
Gaetanbrl Nov 29, 2024
11178e3
translate comments
Gaetanbrl Nov 29, 2024
1b6cfb8
reset active state on edit close
Gaetanbrl Nov 29, 2024
2481835
modify dnd to fix layers drop in groups panel
LPoin Nov 29, 2024
4dc35a2
modify dnd function
LPoin Nov 29, 2024
44c6671
fix addAndConfigLayer method
Gaetanbrl Nov 29, 2024
03fc729
case if no group for addlayer
Gaetanbrl Nov 29, 2024
14dbfef
hide groups panel at theme creation
LPoin Nov 29, 2024
a9a6fea
issue-294 clean groups parsing
LPoin Dec 2, 2024
a12de65
prevents editing title for imported theme
LPoin Dec 3, 2024
35f69b9
fix layers error if don't exist when drag n drop
LPoin Dec 3, 2024
5903374
add index.html to hide groups panel
LPoin Dec 3, 2024
acb1bd8
fix groupid issue
LPoin Dec 4, 2024
e090b19
fix several issues about drag n drop and saving after d'n'd
LPoin Dec 6, 2024
36c5915
fix newTheme default behaviour && error from generic modal
LPoin Dec 6, 2024
d7ea686
fix sortable after publication
LPoin Dec 10, 2024
fca6377
Clean Sortable instances on XML reloading
Gaetanbrl Dec 11, 2024
3e35803
fix #344 - get layer by ID from group and theme
Gaetanbrl Dec 13, 2024
0268d12
pretty
Gaetanbrl Dec 13, 2024
3bbd945
#341 - pass layer as str XML correctly
Gaetanbrl Dec 13, 2024
8e0e1a4
pretty
Gaetanbrl Dec 13, 2024
d1301ad
fix error with attributefilter
Gaetanbrl Dec 13, 2024
a0520af
Fix groupId error and showintoc default state #323 #330
Gaetanbrl Dec 16, 2024
a10e9f6
hide blue user select from draggable tree
Gaetanbrl Dec 16, 2024
fa46bbe
ease scroll on drag event #345
Gaetanbrl Dec 16, 2024
e01c2c9
fix overflow y value #345
Gaetanbrl Dec 16, 2024
cf40969
fix delete layer from group
Gaetanbrl Dec 16, 2024
5b83411
remove height css constraint
Gaetanbrl Dec 16, 2024
3b9e772
Fix group index on drag drop
Gaetanbrl Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions css/bootstrap.css
Original file line number Diff line number Diff line change
Expand Up @@ -3850,9 +3850,9 @@ input[type="button"].btn-block {
.list-group-item {
position: relative;
display: block;
padding: 0.9rem 1.25rem;
padding: 0.5rem 0.75rem;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.125); }
}
.list-group-item:first-child {
border-top-left-radius: inherit;
border-top-right-radius: inherit; }
Expand Down
14 changes: 13 additions & 1 deletion css/mviewerstudio.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@
.list-group-item {
background-color: #ffffff00;
}

.group_list {
background-color: #e1e1e1;
}

.layer_item {
background-color: #e1e1e1;
}

.group_list .layer_item {
background-color: #c5c5c5;
}

.modal {
overflow-y: auto !important;
Expand Down Expand Up @@ -689,7 +701,7 @@
flex: 1 50%;
}

.themes-list-item .theme-layer-list {
.themes-list-item .theme-layer-list .theme-group-list {
flex: 1!important;
}

Expand Down
223 changes: 196 additions & 27 deletions js/mviewerstudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,22 +355,10 @@ var deleteLayerItem = function (btn, themeid) {
el && el.parentNode.removeChild(el);
};

var sortableThemeList = Sortable.create(document.getElementById("themes-list"), {
handle: ".moveList",
animation: 150,
ghostClass: "ghost",
onEnd: function (evt) {
sortThemes();
},
});

sortThemes = function () {
var orderedThemes = {};
$(".themes-list-item").each(function (i, item) {
var id = $(this).attr("data-themeid");
orderedThemes[id] = config.themes[id];
});
config.themes = orderedThemes;
var deleteGroupItem = function (btn, themeid) {
var el = $(btn).closest(".list-group-item")[0];
deleteGroup(el.id, themeid);
el && el.parentNode.removeChild(el);
};

setConf = (key, value) => {
Expand All @@ -391,20 +379,41 @@ $("input[type=file]").change(function () {
loadApplicationParametersFromFile();
});

var addLayer = function (title, layerid, themeid) {
var addLayer = function (title, layerid, themeid, groupid) {
// test if theme is saved
if (!config.themes[themeid]) {
saveThemes();
}
var item = $(`#themeLayers-${themeid}`).append(`
<div class="list-group-item layers-list-item" data-layerid="${layerid}">
var item = $(groupid ? `#${groupid} .list-group` : `#themeLayers-${themeid}`).append(`
<div id="${layerid}" class="layer_item list-group-item layers-list-item nested-3" data-layerid="${layerid}" data-themeid="${themeid}" data-groupid="${groupid}">
<span class="layer-name moveList">${title}</span>
<div class="layer-options-btn" style="display:inline-flex; justify-content: end;">
<button class="btn btn-sm btn-secondary" onclick={mv.setCurrentThemeId("${themeid}");}><span class="layer-move moveList" i18n="move" title="Déplacer"><i class="bi bi-arrows-move"></i></span></button>
<button class="btn btn-sm btn-secondary deleteLayerButton" onclick="deleteLayerItem(this, '${themeid}');"><span class="layer-remove" i18n="delete" title="Supprimer"><i class="bi bi-x-circle"></i></span></button>
<button class="btn btn-sm btn-info" onclick="editLayer(this, '${themeid}', '${layerid}');"><span class="layer-edit" i18n="edit_layer" title="Editer cette couche"><i class="bi bi-gear-fill"></i></span></button>
</div>
</div>`);
return item;
};

var addGroup = (themeid, title, groupId) => {
// test if theme is saved
if (!config.themes[themeid]) {
saveThemes();
}
const item = $(`#themeGroups-${themeid}`).append(`
<div id="${groupId}" class="group-item list-group-item nested-2" data-themeid="${themeid}">
<div class="layers-list-item">
<input type="text" class="group-name form-control col-4 d-inline" value="${title}" aria-label="title">
<div class="layer-options-btn" style="display:inline-flex; justify-content: end;">
<button class="btn btn-sm btn-secondary" onclick={mv.setCurrentThemeId("${themeid}");}><span class="layer-move moveList" i18n="move" title="Déplacer"><i class="bi bi-arrows-move"></i></span></button>
<button class="btn btn-sm btn-secondary deleteLayerButton" onclick="deleteGroupItem(this, '${themeid}');"><span class="group-remove" i18n="delete" title="Supprimer"><i class="bi bi-x-circle"></i></span></button>
</div>
</div>
<div class="layer_item list-group list-group-item nested-sortable mt-3 mb-2 min-h-1"></div>
</div>`);
initializeNestedSortables();
return item;
};

var editLayer = function (item, themeid, layerid) {
Expand All @@ -425,7 +434,6 @@ var editLayer = function (item, themeid, layerid) {

var importThemes = function () {
console.groupCollapsed("importThemes");
//console.log("external theme to import", _conf.external_themes.data);
$("#tableThemaExt .selected").each(function (id, item) {
var url = $(item).attr("data-url");
var id = $(item).attr("data-theme-id");
Expand All @@ -435,23 +443,143 @@ var importThemes = function () {
$("#mod-themesview").modal("hide");
};

sortThemes = function () {
var orderedThemes = {};
$(".themes-list-item").each(function (i, item) {
var id = $(this).attr("data-themeid");
orderedThemes[id] = config.themes[id];
});
config.themes = orderedThemes;
};

var sortableThemeList = Sortable.create(document.getElementById("themes-list"), {
handle: ".moveList",
animation: 150,
ghostClass: "ghost",
onEnd: function (evt) {
sortThemes();
},
});

var sortableElement = function (targetId, callback) {
Sortable.create(document.getElementById(targetId), {
handle: ".moveList",
animation: 150,
ghostClass: "ghost",
fallbackOnBody: true,
swapThreshold: 0.65,
onEnd: function (evt) {
callback(evt);
},
});
};
sortableElement("themes-list", sortThemes);

function initializeNestedSortables() {
const nestedSortables = document.querySelectorAll(".nested-sortable");

nestedSortables.forEach((sortableElement) => {
if (!sortableElement.getAttribute("data-sortable-initialized")) {
new Sortable(sortableElement, {
handle: ".moveList",
animation: 150,
ghostClass: "ghost",
fallbackOnBody: true,
swapThreshold: 0.65,
group: {
name: "nested",
pull: true,
put: true,
},
onEnd: function (evt) {
const item = evt.item;
const fromThemeId = evt.from.closest(".themes-list-item")?.id;
const fromGroupId = evt.from.closest(".group-item")?.id
? evt.from.closest(".group-item").id
: null;
const toThemeId = evt.to.closest(".themes-list-item")?.id;
const toGroupId = evt.to.closest(".group-item")?.id
? evt.to.closest(".group-item").id
: null;
const newIndex = evt.newIndex;

item.setAttribute("data-groupid", toGroupId);
item.setAttribute("data-themeid", toThemeId);

// Si item est un layer
if (item.classList.contains("layers-list-item")) {
config.themes[toThemeId].layers.forEach((layer) => {
if (layer.id === item.getAttribute("data-layerid")) {
layer["data-groupid"] = toGroupId;
layer["data-themeid"] = toThemeId;
}
});
// Cherche l'index de départ en fonction de si le layer bougé vient d'un groupe ou un thème
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention aux commentaires en FR (anglais à privilégier)

const index = fromGroupId
? config.themes[fromThemeId].groups
.find((group) => group.id === fromGroupId)
.layers.findIndex((layer) => layer.id === item.id)
: config.themes[fromThemeId].layers.findIndex(
(layer) => layer.id === item.id
);

// Si l'index éxiste, suppr l'item de la position de départ et l'ajoute à l'arrivée
if (index !== -1) {
// Si le thème n'a pas de layer, on set theme.layers à []
if (!config.themes[fromThemeId].layers)
config.themes[fromThemeId].layers = [];
// Si le groupe d'arrivé n'a pas de layers, on set group.layers à []
if (toGroupId)
if (
!config.themes[toThemeId].groups.find((group) => group.id === toGroupId)
.layers
)
config.themes[toThemeId].groups.find(
(group) => group.id === toGroupId
).layers = [];

const [itemToMove] = fromGroupId
? config.themes[fromThemeId].groups
.find((group) => group.id === fromGroupId)
.layers.splice(index, 1)
: config.themes[fromThemeId].layers.splice(index, 1);
toGroupId
? config.themes[toThemeId].groups
.find((group) => group.id === toGroupId)
.layers.splice(newIndex, 0, itemToMove)
: config.themes[toThemeId].layers.splice(newIndex, 0, itemToMove);
}
} else {
// sinon item est un groupe
config.themes[toThemeId].groups.forEach((group) => {
if (group.id === item.getAttribute("data-groupid")) {
group["data-themeid"] = toThemeId;
}
});
const index = config.themes[fromThemeId].groups.findIndex(
(group) => group.id === item.id
);
if (index !== -1) {
const [itemToMove] = config.themes[fromThemeId].groups.splice(index, 1);
config.themes[toThemeId].groups.push(itemToMove);
}
}
},
});
// Marquer cet élément comme "initialisé" pour éviter les doublons
sortableElement.setAttribute("data-sortable-initialized", true);
}
});
}

// Initialisation au chargement du DOM
initializeNestedSortables();

var addTheme = function (title, collapsed, themeid, icon, url, layersvisibility) {
if (url) {
//external theme
$("#themes-list").append(`
<div class="list-group-item list-group-item themes-list-item" data-theme-url="${url}" data-theme="${title}" data-themeid="${themeid}" data-theme-collapsed="${collapsed}" data-theme-icon="${icon}" data-theme-layersvisibility="${layersvisibility}">
<div class="list-group-item bg-light themes-list-item my-2" data-theme-url="${url}" data-theme="${title}" data-themeid="${themeid}" data-theme-collapsed="${collapsed}" data-theme-icon="${icon}" data-theme-layersvisibility="${layersvisibility}">
<div class="theme-infos">
<span class="theme-name moveList" contentEditable="true">${title}</span><span class="theme-infos-layer">Ext.</span>
</div>
Expand All @@ -463,25 +591,29 @@ var addTheme = function (title, collapsed, themeid, icon, url, layersvisibility)
</div>`);
} else {
$("#themes-list").append(
`<div class="list-group-item themes-list-item" id="${themeid}" data-theme="${title}" data-themeid="${themeid}" data-theme-collapsed="${collapsed}" data-theme-icon="${icon}">
`<div class="list-group-item bg-light themes-list-item nested-1 my-2" id="${themeid}" data-theme="${title}" data-themeid="${themeid}" data-theme-collapsed="${collapsed}" data-theme-icon="${icon}">
<div class="theme-infos ">
<span type="button" class="selected-icon ${icon} picker-button" data-bs-target="#iconPicker" data-bs-toggle="modal"></span>
<input type="text" class="theme-name" value="${title}" aria-label="title">
<input type="text" class="theme-name form-control col-6 d-inline" value="${title}" aria-label="title">
<span class="theme-infos-layer">0</span>
<div class="custom-control custom-switch m-2">
<input type="checkbox" class="custom-control-input" id="${themeid}-theme-edit-collapsed" ${collapsed === "false" ? "checked" : ""}>
<label class="custom-control-label" for="${themeid}-theme-edit-collapsed"><span i18n="modal.theme.paramspanel.opt_unfolded">Déroulée par défaut</span></label>
</div>
</div>
<div class="theme-options-btn text-right">
<button onclick="mv.setCurrentThemeId('${themeid}'), mv.getConfGroups();" class="btn btn-sm btn-outline-info" id="btn-addGroup-${themeid}" data-themeid="${themeid}" ><i class="bi bi-plus-lg"></i>Groupe</button>
<button onclick={mv.setCurrentThemeId("${themeid}");} class="btn btn-sm btn-outline-info" id="btn-addLayer-${themeid}" data-bs-target="#mod-layerNew" data-themeid="${themeid}" data-bs-toggle="modal"><i class="bi bi-plus-lg"></i> Ajouter une donnée</button>
<button class="btn btn-sm btn-secondary"><span class="theme-move moveList" title="Déplacer"><i class="bi bi-arrows-move"></i></span></button>
<button class="btn btn-sm btn-secondary" onclick="deleteThemeItem(this);" ><span class="theme-remove" title="Supprimer"><i class="bi bi-x-circle"></i></span></button>
</div>
<div id="themeLayers-${themeid}" class="theme-layer-list list-group mt-3 mb-2"></div>
</div>
<div>
<div id="themeGroups-${themeid}" class="group_list theme-group-list list-group mt-3 mb-2 p-2 nested-sortable"> Groupes </div>
<div id="themeLayers-${themeid}" class="layer_item theme-layer-list list-group mt-3 mb-2 p-2 nested-sortable"> Couches </div>
</div>
</div>`
);
sortableElement("themeLayers-" + themeid, sortLayers);
initializeNestedSortables();
}
config.themes[themeid] = {
title: title,
Expand Down Expand Up @@ -539,6 +671,29 @@ var saveThemes = function () {
}
};

var saveGroups = () => {
const themes = $(".themes-list-item");
for (i = 0; i < themes.length; i++) {
const theme = themes[i];
const themeId = theme.getAttribute("data-themeid");
const groups = $(`#${themeId}`).find(".group-item");

for (j = 0; j < groups.length; j++) {
const group = groups[j];
const groupId = group.id;

const gr = $(`div[id="${groupId}"]`);
const groupTitle = gr.find(".group-name").val();

if (config.themes[themeId].groups) {
config.themes[themeId].groups.find((group) => group.id === groupId).id = groupId;
config.themes[themeId].groups.find((group) => group.id === groupId).title =
LPoin marked this conversation as resolved.
Show resolved Hide resolved
groupTitle;
}
}
}
};

var editThemeExt = function (item) {
$("#themes-list .list-group-item").removeClass("active");
$(item).parent().parent().addClass("active");
Expand Down Expand Up @@ -578,6 +733,13 @@ var deleteLayer = function (layerid, themeid) {
config.themes[themeid].layers.splice(index, 1);
};

var deleteGroup = function (groupid, themeid) {
var index = config.themes[themeid].groups.findIndex(function (g) {
return g.id === groupid;
});
config.themes[themeid].groups.splice(index, 1);
};

var createId = function (obj) {
var d = new Date();
var df =
Expand Down Expand Up @@ -848,6 +1010,7 @@ var getConfig = () => {
// Respect theme order
$(".themes-list-item").each(function (id, theme) {
saveThemes();
saveGroups();
var themeid = $(theme).attr("data-themeid");
if (config.themes[themeid]) {
var t = config.themes[themeid];
Expand Down Expand Up @@ -883,10 +1046,17 @@ var getConfig = () => {
'">',
];
}
// push groupes
$(t.groups).each((i, g) => {
var group = mv.writeGroupNode(g);
theme.push(group);
});
// push layers hors groupes
$(t.layers).each(function (i, l) {
var layer = mv.writeLayerNode(l);
theme.push(layer);
});

themes.push(theme.join(" "));
themes.push(padding(4) + "</theme>");
}
Expand All @@ -912,7 +1082,6 @@ var getConfig = () => {
themes.join(" "),
padding(0) + "</config>",
];

return conf;
};

Expand Down
Loading