ministerchief commited on
Commit
3f44b33
·
verified ·
1 Parent(s): cb1c1d9

Upload 15 files

Browse files
Hugging Face – The AI community building the future..html ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, render_template, request
2
+ import qrcode
3
+ from PIL import Image
4
+ import os
5
+ import pandas as pd
6
+ import requests
7
+ from io import StringIO
8
+ from urllib.parse import quote
9
+
10
+ app = Flask(__name__)
11
+
12
+ UPLOAD_FOLDER = "static/generated"
13
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
14
+
15
+ # 🔗 Google Sheet Info
16
+ SHEET_ID = "1F90Q1scHpX4U_OIBDA_yZF3BozUGfJtl-1XucV4XBCM"
17
+ GID = "0"
18
+
19
+ GOOGLE_SHEET_CSV = f"https://docs.google.com/spreadsheets/d/{SHEET_ID}/export?format=csv&gid={GID}"
20
+
21
+
22
+ def fetch_sheet():
23
+ try:
24
+ response = requests.get(GOOGLE_SHEET_CSV)
25
+ response.raise_for_status()
26
+
27
+ df = pd.read_csv(StringIO(response.text))
28
+ df.columns = df.columns.str.strip().str.lower()
29
+
30
+ if "asset id" not in df.columns:
31
+ return None
32
+
33
+ df.rename(columns={"asset id": "Asset ID"}, inplace=True)
34
+ return df
35
+
36
+ except:
37
+ return None
38
+
39
+
40
+ @app.route("/")
41
+ def home():
42
+ return render_template("index.html")
43
+
44
+
45
+ @app.route("/generate", methods=["POST"])
46
+ def generate_qr():
47
+ asset_id = request.form["data"].strip()
48
+ fill_color = request.form["fill_color"]
49
+ back_color = request.form["back_color"]
50
+ size = int(request.form["size"])
51
+ logo = request.files.get("logo")
52
+
53
+ df = fetch_sheet()
54
+ if df is None:
55
+ return render_template("index.html", error="Unable to fetch sheet")
56
+
57
+ df["Asset ID"] = df["Asset ID"].astype(str).str.strip()
58
+
59
+ result = df[df["Asset ID"].str.lower() == asset_id.lower()]
60
+
61
+ if result.empty:
62
+ return render_template("index.html", error="❌ Asset Not Found")
63
+
64
+ row = result.iloc[0]
65
+
66
+ # QR now stores asset URL
67
+ asset_url = request.host_url + "asset/" + quote(asset_id)
68
+
69
+ qr = qrcode.QRCode(
70
+ version=None,
71
+ error_correction=qrcode.constants.ERROR_CORRECT_H,
72
+ box_size=size,
73
+ border=4,
74
+ )
75
+
76
+ qr.add_data(asset_url)
77
+ qr.make(fit=True)
78
+
79
+ img = qr.make_image(fill_color=fill_color, back_color=back_color).convert("RGB")
80
+
81
+ if logo and logo.filename != "":
82
+ logo_img = Image.open(logo)
83
+ logo_size = img.size[0] // 4
84
+ logo_img = logo_img.resize((logo_size, logo_size))
85
+
86
+ pos = (
87
+ (img.size[0] - logo_size) // 2,
88
+ (img.size[1] - logo_size) // 2
89
+ )
90
+
91
+ img.paste(logo_img, pos)
92
+
93
+ qr_path = os.path.join(UPLOAD_FOLDER, "qr.png")
94
+ img.save(qr_path)
95
+
96
+ asset_info = {
97
+ "Asset ID": row.get("Asset ID", ""),
98
+ "Asset Type": row.get("asset type", ""),
99
+ "Asset Name": row.get("asset name", ""),
100
+ "Allotted To": row.get("allotted to", ""),
101
+ "Department": row.get("department", ""),
102
+ }
103
+
104
+ return render_template(
105
+ "index.html",
106
+ qr_image="generated/qr.png",
107
+ asset=asset_info
108
+ )
109
+
110
+
111
+ @app.route("/asset/<path:asset_id>")
112
+ def show_asset(asset_id):
113
+ df = fetch_sheet()
114
+ if df is None:
115
+ return "<h3>Unable to fetch data</h3>"
116
+
117
+ df["Asset ID"] = df["Asset ID"].astype(str).str.strip()
118
+
119
+ result = df[df["Asset ID"].str.lower() == asset_id.lower()]
120
+
121
+ if result.empty:
122
+ return "<h3>Asset Not Found</h3>"
123
+
124
+ row = result.iloc[0]
125
+
126
+ asset_info = {
127
+ "Asset ID": row.get("Asset ID", ""),
128
+ "Asset Type": row.get("asset type", ""),
129
+ "Asset Name": row.get("asset name", ""),
130
+ "Allotted To": row.get("allotted to", ""),
131
+ "Department": row.get("department", ""),
132
+ }
133
+
134
+ return render_template("asset_card.html", asset=asset_info)
135
+
136
+
137
+ if __name__ == "__main__":
138
+ app.run(debug=True)
assets.csv ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Asset_ID,Asset_Type,Asset_Name,Allotted_To,Department
2
+ NIELIT/CH-RPR/m-Table/05,FURNITURE,TABLE,SAMSAD ALI,TRAINING
3
+ NIELIT/CH/EE-Chair/2014/120-54,FURNITURE,CHAIR,SAMSAD ALI,TRAINING
4
+ NIELIT/CH-RPR/DELL-i5/2020/80-20,PC,DELL,SAMSAD ALI,TRAINING
5
+ NIELIT/CH-RPR/m-ELAN-DESK-1/2014/59-51,FURNITURE,TABLE,PRAKASH PRATIK,TRAINING
6
+ NIELIT/CH/EE-Chair/2014/120-86,FURNITURE,CHAIR,PRAKASH PRATIK,TRAINING
7
+ NIELIT/CH-RPR/DELL-i5/AIO/2020/20-1,PC,DELL,PRAKASH PRATIK,TRAINING
8
+ NIELIT/CH-RPR/m-ELAN-DESK-1/2014/59-06,FURNITURE,TABLE,AKASH SARAN,TRAINING
9
+ NIELIT/CH/EE-Chair/2014/120-89,FURNITURE,CHAIR,AKASH SARAN,TRAINING
10
+ NIELIT/CH-RPR/ZENIX/2024/14,PC,DELL,AKASH SARAN,TRAINING
11
+ NIELIT/CH-RPR/m-ELAN-DESK-1/2014/59-29,FURNITURE,TABLE,SNEASIS JOARDAR,TRAINING
12
+ NIELIT/CH/EE-Chair/2014/120-20,FURNITURE,CHAIR,SNEASIS JOARDAR,TRAINING
13
+ NIELIT/CH-RPR/DELL-i5/AIO/2020/20-2,PC,DELL,SNEASIS JOARDAR,TRAINING
14
+ NIELIT/CH-RPR/m-ELAN-DESK-1/2014/59-50,FURNITURE,TABLE,RAMINDER SINGH,TRAINING
15
+ NIELIT/CH/EE-Chair/2014/120-13,FURNITURE,CHAIR,RAMINDER SINGH,TRAINING
16
+ NIELIT/CH-RPR/DELL-i7/2020/15-12,PC,DELL,RAMINDER SINGH,TRAINING
download (1).jpg ADDED
download.jpg ADDED
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Flask
2
+ qrcode
3
+ Pillow
4
+ Werkzeug
5
+ pandas
6
+ requests
static/generated/qr.png ADDED
static/script.js ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ===============================
2
+ // Select Form Elements
3
+ // ===============================
4
+ const dataInput = document.querySelector("input[name='data']");
5
+ const fillColorInput = document.querySelector("input[name='fill_color']");
6
+ const backColorInput = document.querySelector("input[name='back_color']");
7
+ const sizeSelect = document.querySelector("select[name='size']");
8
+ const logoInput = document.querySelector("input[name='logo']");
9
+ const form = document.querySelector("form");
10
+
11
+ // ===============================
12
+ // Create QR Preview Container
13
+ // ===============================
14
+ const previewContainer = document.createElement("div");
15
+ previewContainer.style.marginTop = "20px";
16
+ previewContainer.style.textAlign = "center";
17
+
18
+ const previewTitle = document.createElement("h3");
19
+ previewTitle.innerText = "Live QR Preview";
20
+ previewTitle.style.marginBottom = "10px";
21
+
22
+ const previewImg = document.createElement("img");
23
+ previewImg.style.maxWidth = "200px";
24
+ previewImg.style.border = "1px solid #ddd";
25
+ previewImg.style.padding = "10px";
26
+ previewImg.style.borderRadius = "10px";
27
+
28
+ previewContainer.appendChild(previewTitle);
29
+ previewContainer.appendChild(previewImg);
30
+ form.appendChild(previewContainer);
31
+
32
+ // ===============================
33
+ // Generate Live QR Preview
34
+ // ===============================
35
+ function generatePreview() {
36
+ const data = dataInput.value.trim();
37
+ const fillColor = fillColorInput.value;
38
+ const backColor = backColorInput.value;
39
+ const size = parseInt(sizeSelect.value);
40
+
41
+ if (data === "") {
42
+ previewImg.src = "";
43
+ return;
44
+ }
45
+
46
+ const qrSize = size * 25;
47
+
48
+ previewImg.src = `https://api.qrserver.com/v1/create-qr-code/?size=${qrSize}x${qrSize}&data=${encodeURIComponent(data)}&color=${fillColor.replace('#', '')}&bgcolor=${backColor.replace('#', '')}`;
49
+ }
50
+
51
+ // ===============================
52
+ // Event Listeners for Live Update
53
+ // ===============================
54
+ dataInput.addEventListener("input", generatePreview);
55
+ fillColorInput.addEventListener("input", generatePreview);
56
+ backColorInput.addEventListener("input", generatePreview);
57
+ sizeSelect.addEventListener("change", generatePreview);
58
+
59
+ // ===============================
60
+ // Logo Upload Handling
61
+ // ===============================
62
+ // (Logo will be embedded in backend only)
63
+ logoInput.addEventListener("change", function () {
64
+ generatePreview(); // Keep QR preview intact
65
+ });
66
+
67
+ // ===============================
68
+ // Simple Form Validation
69
+ // ===============================
70
+ form.addEventListener("submit", function (e) {
71
+ if (dataInput.value.trim() === "") {
72
+ e.preventDefault();
73
+ alert("Please enter Asset ID or text!");
74
+ dataInput.focus();
75
+ }
76
+ });
static/style.css ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: 'Poppins', sans-serif;
3
+ background: linear-gradient(135deg, #667eea, #764ba2);
4
+ display: flex;
5
+ justify-content: center;
6
+ align-items: center;
7
+ min-height: 100vh;
8
+ padding: 40px 0;
9
+ }
10
+
11
+ /* Bigger Glass Container */
12
+ .container {
13
+ background: rgba(255, 255, 255, 0.15);
14
+ backdrop-filter: blur(15px);
15
+ padding: 60px;
16
+ /* Increased padding */
17
+ border-radius: 25px;
18
+ width: 500px;
19
+ /* Increased width */
20
+ max-width: 95%;
21
+ box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
22
+ color: white;
23
+ animation: fadeIn 1s ease-in-out;
24
+ }
25
+
26
+ /* Bigger Heading */
27
+ .container h2 {
28
+ text-align: center;
29
+ margin-bottom: 35px;
30
+ font-weight: 600;
31
+ font-size: 26px;
32
+ }
33
+
34
+ /* Inputs & Select */
35
+ input,
36
+ select {
37
+ width: 100%;
38
+ margin: 18px 0;
39
+ /* More vertical spacing */
40
+ padding: 15px;
41
+ /* Bigger input size */
42
+ border-radius: 12px;
43
+ border: none;
44
+ outline: none;
45
+ font-size: 15px;
46
+ transition: 0.3s ease;
47
+ }
48
+
49
+ /* Button */
50
+ button {
51
+ width: 100%;
52
+ padding: 15px;
53
+ margin-top: 25px;
54
+ border-radius: 14px;
55
+ border: none;
56
+ background: linear-gradient(45deg, #ff6b6b, #ff9f43);
57
+ color: white;
58
+ font-size: 17px;
59
+ font-weight: 600;
60
+ cursor: pointer;
61
+ transition: 0.4s ease;
62
+ }
templates/assests_card.html ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <title>Asset Details</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+
8
+ <style>
9
+ body {
10
+ font-family: 'Poppins', sans-serif;
11
+ background: linear-gradient(135deg, #667eea, #764ba2);
12
+ display: flex;
13
+ justify-content: center;
14
+ align-items: center;
15
+ height: 100vh;
16
+ margin: 0;
17
+ }
18
+
19
+ .card {
20
+ background: white;
21
+ width: 350px;
22
+ padding: 25px;
23
+ border-radius: 20px;
24
+ box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
25
+ text-align: center;
26
+ }
27
+
28
+ .card h2 {
29
+ margin-bottom: 20px;
30
+ color: #333;
31
+ }
32
+
33
+ .info {
34
+ text-align: left;
35
+ margin-top: 15px;
36
+ }
37
+
38
+ .info p {
39
+ margin: 10px 0;
40
+ font-size: 15px;
41
+ color: #555;
42
+ }
43
+
44
+ .label {
45
+ font-weight: bold;
46
+ color: #222;
47
+ }
48
+
49
+ .badge {
50
+ display: inline-block;
51
+ padding: 5px 12px;
52
+ background: #667eea;
53
+ color: white;
54
+ border-radius: 15px;
55
+ font-size: 12px;
56
+ margin-bottom: 10px;
57
+ }
58
+ </style>
59
+ </head>
60
+
61
+ <body>
62
+
63
+ <div class="card">
64
+ <div class="badge">Asset Verified ✔</div>
65
+ <h2>{{ asset["Asset Name"] }}</h2>
66
+
67
+ <div class="info">
68
+ <p><span class="label">Asset ID:</span> {{ asset["Asset ID"] }}</p>
69
+ <p><span class="label">Type:</span> {{ asset["Asset Type"] }}</p>
70
+ <p><span class="label">Allotted To:</span> {{ asset["Allotted To"] }}</p>
71
+ <p><span class="label">Department:</span> {{ asset["Department"] }}</p>
72
+ </div>
73
+ </div>
74
+
75
+ </body>
76
+
77
+ </html>
templates/index.html ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <title>Smart Asset QR System</title>
6
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
7
+ </head>
8
+
9
+ <body>
10
+
11
+ <div class="container">
12
+ <h2>🏢 Smart Asset QR Generator</h2>
13
+
14
+ {% if error %}
15
+ <p style="color:red;">{{ error }}</p>
16
+ {% endif %}
17
+
18
+ <form action="/generate" method="POST" enctype="multipart/form-data">
19
+
20
+ <input type="text" name="data" placeholder="Enter Asset ID (Example: PC001)" required>
21
+
22
+ <label>QR Color</label>
23
+ <input type="color" name="fill_color" value="#000000">
24
+
25
+ <label>Background Color</label>
26
+ <input type="color" name="back_color" value="#ffffff">
27
+
28
+ <label>QR Size</label>
29
+ <select name="size">
30
+ <option value="8">Small</option>
31
+ <option value="10">Medium</option>
32
+ <option value="12">Large</option>
33
+ </select>
34
+
35
+ <label>Upload Logo (Optional)</label>
36
+ <input type="file" name="logo">
37
+
38
+ <button type="submit">Generate QR</button>
39
+ </form>
40
+
41
+ {% if qr_image %}
42
+ <hr>
43
+ <h3>Generated QR</h3>
44
+ <img src="{{ url_for('static', filename=qr_image) }}" width="200">
45
+
46
+ <h3>Asset Details</h3>
47
+ <p><strong>Asset ID:</strong> {{ asset["Asset ID"] }}</p>
48
+ <p><strong>Type:</strong> {{ asset["Asset Type"] }}</p>
49
+ <p><strong>Name:</strong> {{ asset["Asset Name"] }}</p>
50
+ <p><strong>Allotted To:</strong> {{ asset["Allotted To"] }}</p>
51
+ <p><strong>Department:</strong> {{ asset["Department"] }}</p>
52
+ {% endif %}
53
+
54
+ </div>
55
+
56
+ </body>
57
+
58
+ </html>
uploads/download-removebg-preview.png ADDED
uploads/download.jpg ADDED
uploads/google.png ADDED
uploads/qr.png ADDED