Skip to content

Commit 385d561

Browse files
authored
Merge pull request #26 from kit-data-manager/visual-mapping-options
Visual mapping options
2 parents 62f0fba + f838aa2 commit 385d561

File tree

4 files changed

+217
-76
lines changed

4 files changed

+217
-76
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "This component contains an option to select an input file form which metadata needs to be extracted, an option to search from available mapping schemas whose name will be self explainatory .",
44
"author": "Ajay",
55
"license": "Apache License 2.0",
6-
"version": "0.5.6",
6+
"version": "0.5.7",
77
"private": false,
88
"keywords": [
99
"metadata",

src/main.ts

+109-39
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@ import templateContent from "./template.html?raw";
22
import * as FilePondLib from "filepond";
33
import { FilePond, FilePondOptions } from "filepond";
44
import filepondCSS from "filepond/dist/filepond.min.css?inline";
5-
import typeahead from "typeahead-standalone";
6-
import typeaheadCSS from "typeahead-standalone/dist/basic.css?inline";
75
import customCSS from './style.css?inline';
86

97
const ATTRIBUTES: string[] = ["base-url"];
8+
interface MappingItem {
9+
mappingId: string;
10+
title: string;
11+
description?: string;
12+
mappingType: string;
13+
name: string;
14+
}
1015
class MappingInputProvider extends HTMLElement {
1116
shadowRoot: ShadowRoot;
1217
private testingFileChooser: FilePond | null = null;
1318
// --- Attribute accessible from the HTML tag:
1419
baseUrl: URL = new URL("http://localhost:8090/");
1520
// ---
1621

17-
22+
selectedMappingId: string | null = null;
23+
selectedMappingType: string | null = null;
24+
messageDisplayed: boolean | null = null;
1825
// --- Helper methods
1926
addCssContent(css: string): void {
2027
let styleElem: HTMLStyleElement = document.createElement("style");
@@ -38,7 +45,6 @@ class MappingInputProvider extends HTMLElement {
3845
// Create Shadow DOM
3946
this.shadowRoot = this.attachShadow({ mode: "open" });
4047
this.addCssContent(filepondCSS);
41-
this.addCssContent(typeaheadCSS);
4248
this.addCssContent(customCSS);
4349

4450
// Apply HTML Template to shadow DOM
@@ -86,43 +92,73 @@ class MappingInputProvider extends HTMLElement {
8692
options.maxFiles = 1;
8793
this.testingFileChooser = FilePondLib.create(filepondElement, options);
8894
}
89-
let inputElement: HTMLInputElement = <HTMLInputElement>(
90-
this.shadowRoot.getElementById("mappingchooser")
95+
96+
//Box of detailed contents like image, description of mapping
97+
const mappingIdsEndpoint = this.baseUrl.toString() + "api/v1/mappingAdministration/";
98+
let optionsContainer: HTMLElement = <HTMLInputElement>(
99+
this.shadowRoot.getElementById('options-container')
91100
);
92-
if (inputElement != null) {
93-
typeahead({
94-
input: inputElement,
95-
minLength: -1,
96-
highlight: true,
97-
source: {
98-
prefetch: {
99-
url: this.baseUrl.toString() + "api/v1/mappingAdministration/",
100-
done: false,
101-
},
102-
identifier: "name",
103-
transform: (data) => {
104-
for (let item of data) {
105-
if (typeof item == "object") {
106-
item.name = item.title ? `${item.mappingId} - ${item.title}` : item.mappingId;
101+
// Remove any existing event listeners before adding a new one
102+
optionsContainer.removeEventListener("click", this.handleButtonClick.bind(this));
103+
104+
// Add the event listener
105+
optionsContainer.addEventListener("click", this.handleButtonClick.bind(this));
106+
107+
fetch(mappingIdsEndpoint).then(response => response.json())
108+
.then((mappingIdsData: MappingItem[]) => {
109+
const mappingIds = mappingIdsData.map((item: MappingItem) => ({
110+
id: item.mappingId,
111+
title: item.title,
112+
description: item.description,
113+
type: item.mappingType
114+
}));
115+
optionsContainer.innerHTML = '';
116+
mappingIds.forEach(mapping => {
117+
const division = document.createElement("div")
118+
division.classList.add("cards");
119+
division.innerHTML = `
120+
<!-- Commenting out the image section -->
121+
<!--
122+
<img class="mapping-image" src="${this.getImageByType(mapping.type)}" alt="Mapping Image" />
123+
-->
124+
<h3>${mapping.title}</h3>
125+
<span class="home-text10 section-description">
126+
<br>
127+
<span style="display:inline-block; overflow: auto; height: 124px;">
128+
${mapping.description}
129+
</span>
130+
</span>
131+
<button class ="selection-button " id="mapping-button-${mapping.id}" >Select</button>
132+
`;
133+
const button = division.querySelector(`#mapping-button-${mapping.id}`);
134+
if (button) {
135+
button.addEventListener("click", () => {
136+
this.selectedMappingId = mapping.id;
137+
if (!this.messageDisplayed) {
138+
const fileInput = this.shadowRoot.querySelector("#fileUpload");
139+
const messageElement = document.createElement("div");
140+
messageElement.innerText = "Please upload file and then click on map document to extract metadata";
141+
messageElement.style.marginBottom = "10px"; // Add some bottom margin for spacing
142+
messageElement.classList.add("message");
143+
if (fileInput != null && fileInput.parentNode != null) {
144+
fileInput.parentNode.insertBefore(messageElement, fileInput);
145+
}
146+
this.messageDisplayed = true;
107147
}
108-
}
109-
return data
110-
},
111-
dataTokens: ["description"],
112-
identity: (suggestion) => `${suggestion.mappingId}${suggestion.title}`
113-
},
114-
preventSubmit: true,
115-
});
116-
} else {
117-
console.error("Could not find element for mapping selector (typeahead).");
118-
}
148+
});
149+
}
150+
optionsContainer.appendChild(division);
151+
})
152+
}).catch(error => {
153+
console.error('Error while fetch Mapping Ids' + error)
154+
})
155+
119156
}
120157

121158
/**
122159
* Invoked each time the custom element is disconnected from the document's DOM.
123160
*/
124161
disconnectedCallback(): void {
125-
return;
126162
}
127163

128164
/**
@@ -156,12 +192,8 @@ class MappingInputProvider extends HTMLElement {
156192
executeMapping(): Promise<any>;
157193
async executeMapping(download: boolean = false): Promise<any> {
158194
document.body.style.cursor = 'wait';
159-
let inputElement: HTMLInputElement = <HTMLInputElement>(
160-
this.shadowRoot.getElementById("mappingchooser")
161-
);
162-
const selectedValue = inputElement?.value;
163-
const selectedMappingId = selectedValue?.split("-")[0].trim();
164-
if (this.testingFileChooser != null) {
195+
const selectedMappingId = this.selectedMappingId;
196+
if (selectedMappingId && this.testingFileChooser != null) {
165197
const uploadedFile = this.testingFileChooser.getFile();
166198
if (uploadedFile != null) {
167199
const execUrl = this.baseUrl.toString() + "api/v1/mappingExecution/" + selectedMappingId;
@@ -210,6 +242,44 @@ class MappingInputProvider extends HTMLElement {
210242
this.shadowRoot.removeChild(element);
211243
URL.revokeObjectURL(element.href);
212244
}
245+
246+
/**
247+
* In case if you want to show images according the the mappingType eg: SEM,TEM etc yu can use this method
248+
*/
249+
getImageByType(mappingType: string): string {
250+
if (mappingType.includes("GEMMA")) {
251+
// Assuming gemma.png is in the assets/images folder
252+
return "/images/gemma.png";
253+
} else if (mappingType.includes("SEM")) {
254+
// Assuming sem.png is in the assets/images folder
255+
return "/images/tem.png";
256+
} else if (mappingType.includes("TEM")) {
257+
// Assuming tem.png is in the assets/images folder
258+
return "/images/tem.png";
259+
} else {
260+
// Default image path when no mapping type matches
261+
return "/images/other.png";
262+
}
263+
}
264+
265+
/**
266+
* We have used this method to capture mapping id which is later used to execute mapping
267+
*/
268+
private handleButtonClick(event: Event) {
269+
const selectedButton = event.target as HTMLElement;
270+
console.log(selectedButton);
271+
// Remove the "selected" class from all buttons
272+
const buttons = this.shadowRoot.querySelectorAll(".selection-button");
273+
buttons.forEach((button) => {
274+
button.classList.remove("selected-id");
275+
});
276+
// Add the "selected" class to the clicked button
277+
selectedButton.classList.add("selected-id");
278+
279+
// Get the selected mapping ID from the button's ID
280+
const selectedMappingId = selectedButton.id.replace("mapping-button-", "");
281+
this.selectedMappingId = selectedMappingId;
282+
}
213283
}
214284

215285
// Custom Elements:

src/style.css

+97-32
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1-
input {
2-
padding: 0.625rem;
3-
font-size: 0.875rem;
4-
border: 1px solid #ccc;
5-
border-radius: 0.25rem;
6-
width: 23.625rem;
7-
}
8-
91
#fileUpload {
102
padding: 0.625rem;
113
width: auto;
124
margin: 2.5rem auto 4rem;
135
border: none;
146
background-color: #d9eaea;
15-
box-shadow: 0 0.125rem 0.3125rem rgba(0, 0, 0, 0.3);
7+
/* box-shadow: 0 0.125rem 0.3125rem rgba(0, 0, 0, 0.3); */
168
transition: all 0.3s ease;
179
font-size: 1.5625rem;
18-
color: #f80abd;
19-
width: calc(90% - 2.125rem);
20-
margin-left: auto;
21-
margin-right: auto;
10+
/* color: #f80abd; */
11+
/* width: calc(90% - 2.125rem); */
12+
margin-left: 25px;
13+
margin-right: 25px;
2214
height: 9.375rem;
2315
text-align-last: center;
2416
}
@@ -42,33 +34,106 @@ button:hover {
4234
transform: translateY(-0.125rem);
4335
}
4436

45-
.mapping-container {
46-
max-width: 37.5rem;
47-
margin: 0 auto;
37+
.home-text08 {
38+
font-size: 2rem;
39+
}
40+
41+
.home-text09 {
42+
font-size: 1.125rem;
43+
}
44+
45+
.message {
46+
background-color: #eaf0b0;
47+
align-content: center;
4848
text-align: center;
49+
color: #333;
50+
padding: 0.625rem 1.25rem;
51+
margin-bottom: 0.625rem;
52+
margin-left: 1.5625rem;
53+
margin-right: 1.5625rem;
54+
font-size: 1rem;
55+
font-weight: bold;
56+
border-radius: 0.3125rem;
57+
animation: fade-in 0.3s ease-in-out;
4958
}
5059

51-
.mapping-title {
52-
font-size: 2rem;
53-
margin-bottom: 1.25rem;
60+
.selection-button.selected-id {
61+
/* Add your selected button styles here */
62+
background-color: rgb(137, 202, 84);
63+
color: #fff;
5464
}
5565

56-
.mapping-input-container {
66+
.mapping-options {
5767
display: flex;
68+
flex-direction: column;
5869
align-items: center;
59-
max-width: 25rem;
60-
margin: 0 auto;
61-
background-color: #fff;
62-
border-radius: 3.125rem;
63-
padding: 0.625rem 1.25rem;
64-
box-shadow: 0 0.125rem 0.3125rem rgba(0, 0, 0, 0.3);
65-
width: fit-content;
70+
padding: 1.25rem;
6671
}
6772

68-
.mapping-input {
69-
flex: 1;
70-
border: none;
71-
outline: none;
72-
font-size: 1.125rem;
73+
.container-wrapper {
74+
display: flex;
75+
justify-content: center;
76+
width: 100%;
77+
overflow-x: auto;
78+
align-self: center;
79+
padding: 1.25rem;
80+
}
81+
82+
.options-container {
83+
display: flex;
84+
flex-wrap: nowrap;
85+
justify-content: center;
86+
overflow-x: auto;
87+
padding-bottom: 0.625rem;
88+
}
89+
90+
.cards {
91+
flex: 0 0 calc(25% - 1.25rem);
92+
display: flex;
93+
flex-wrap: wrap;
94+
flex-direction: column;
95+
align-items: center;
96+
justify-content: center;
97+
text-align: center;
7398
padding: 0.625rem;
99+
box-sizing: border-box;
100+
border: 1px solid #ccc;
101+
margin: 0.625rem;
102+
overflow: hidden;
103+
position: relative;
104+
min-width: 12.5rem;
105+
/* Added minimum width for better mobile view */
106+
background-color: #eef3f4;
107+
/* Add your desired background color here */
108+
}
109+
110+
.cards img {
111+
max-width: 6.25rem;
112+
margin-bottom: 0.625rem;
113+
}
114+
115+
.cards h2 {
116+
margin-bottom: 0.625rem;
117+
white-space: normal;
118+
overflow-wrap: break-word;
119+
cursor: pointer;
120+
width: 100%;
121+
background-color: #c49898;
122+
color: #333;
123+
padding: 0.3125rem;
124+
border-radius: 0.3125rem;
125+
}
126+
127+
.cards div {
128+
text-align: center;
129+
white-space: normal;
130+
}
131+
132+
.home-heading-container {
133+
text-align: center;
134+
}
135+
136+
.section-heading {
137+
/* background-color: #c52222; */
138+
font-size: large;
74139
}

src/template.html

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
<div class="mapping-container">
2-
<h2 class="mapping-title">Choose a Mapping</h2>
3-
<div class="mapping-input-container">
4-
<input id="mappingchooser" class="mapping-input" placeholder="Select or search your mapping here." />
1+
<div id="options" class="mapping-options">
2+
<div class="home-heading-container">
3+
<h1 class="home-text08">Mapping Component</h1>
4+
<span class="home-text09 content">
5+
Choose a suitable mapping from available options
6+
</span>
7+
</div>
8+
<div class="container-wrapper">
9+
<div id="options-container" class="options-container">
10+
</div>
511
</div>
612
</div>
713
<input type="file" id="fileUpload" />

0 commit comments

Comments
 (0)