Finished first full flow design. All updates are displayed on the board.
This commit is contained in:
99
server.py
99
server.py
@@ -1,33 +1,58 @@
|
|||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from flask import Flask, jsonify, render_template, request
|
from flask import Flask, jsonify, render_template, request
|
||||||
from mta_manager import MTA
|
from mta_manager import MTA
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = "SuperSecretDontEvenTryToGuessMeGGEZNoRe"
|
app.secret_key = "SuperSecretDontEvenTryToGuessMeGGEZNoRe"
|
||||||
app.debug = True
|
app.debug = True
|
||||||
app._static_folder = os.path.abspath("templates/static/")
|
app._static_folder = os.path.abspath("templates/static/")
|
||||||
|
|
||||||
subway_data = {}
|
|
||||||
|
|
||||||
stops = pd.read_csv("stops.txt")
|
stops = pd.read_csv("stops.txt")
|
||||||
|
stop_ids = ["127S", "127N", "A27N", "A27S"]
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", methods=["GET"])
|
@app.route("/", methods=["GET"])
|
||||||
def index():
|
def index():
|
||||||
# TODO: Shove this into a sqlite database
|
# TODO: Shove this into a sqlite database
|
||||||
station_names = sorted(list(set(stops["stop_name"].to_list())))
|
station_names = sorted(list(set(stops["stop_name"].to_list())))
|
||||||
print(station_names)
|
return render_template(
|
||||||
return render_template("layouts/index.html", station_names=station_names)
|
"layouts/index.html",
|
||||||
|
station_names=station_names,
|
||||||
|
station_1="42 St-Port Authority Bus Terminal",
|
||||||
|
station_2="Times Sq-42 St"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def link_to_station(data):
|
||||||
|
linked_data = {}
|
||||||
|
for key, value in data.items():
|
||||||
|
stop_name = stops.loc[stops["stop_id"] == key]
|
||||||
|
stop_name = stop_name["stop_name"].values[0]
|
||||||
|
if stop_name not in linked_data:
|
||||||
|
linked_data[stop_name] = {}
|
||||||
|
if "N" in key:
|
||||||
|
linked_data[stop_name]["North"] = value
|
||||||
|
elif "S" in key:
|
||||||
|
linked_data[stop_name]["South"] = value
|
||||||
|
return linked_data
|
||||||
|
|
||||||
|
|
||||||
@app.route("/mta_data", methods=["POST"])
|
@app.route("/mta_data", methods=["POST"])
|
||||||
def get_mta_data():
|
def get_mta_data():
|
||||||
content = request.json
|
station = request.json["station"]
|
||||||
|
print(jsonify(
|
||||||
|
subway_data[station]
|
||||||
|
))
|
||||||
return jsonify(
|
return jsonify(
|
||||||
subway_data
|
subway_data[station]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -35,56 +60,52 @@ def get_mta_data():
|
|||||||
def get_routes():
|
def get_routes():
|
||||||
return jsonify()
|
return jsonify()
|
||||||
|
|
||||||
@app.route("/get_stop_id/<stop_name>", methods=["GET"])
|
|
||||||
def get_stop_id(stop_name):
|
@app.route("/get_stop_id", methods=["POST"])
|
||||||
|
def get_stop_id():
|
||||||
|
print(request.json)
|
||||||
|
stop_name = request.json["stop_name"]
|
||||||
print(stop_name)
|
print(stop_name)
|
||||||
rows = stops.loc[stops["stop_name"] == stop_name]
|
rows = stops.loc[stops["stop_name"] == stop_name]
|
||||||
print(rows)
|
print(rows)
|
||||||
return str(rows)
|
return jsonify({"station_changed": True})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def ack():
|
|
||||||
print('message was received!')
|
|
||||||
|
|
||||||
|
|
||||||
class threadWrapper(threading.Thread):
|
|
||||||
def __init__(self, run, controller):
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
self.run = run
|
|
||||||
self.controller = controller
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.run()
|
|
||||||
|
|
||||||
|
|
||||||
async def mta_callback(routes):
|
|
||||||
global subway_data
|
|
||||||
# TODO: Do away with this and throw it into websockets
|
|
||||||
subway_data = mtaController.convert_routes_to_station_first(routes)
|
|
||||||
|
|
||||||
|
|
||||||
def start_mta():
|
|
||||||
mtaController.add_callback(mta_callback)
|
|
||||||
mtaController.start_updates()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
api_key = os.getenv('MTA_API_KEY', '')
|
api_key = os.getenv('MTA_API_KEY', '')
|
||||||
mtaController = MTA(
|
mtaController = MTA(
|
||||||
# TODO: Update to only work with station names - need to be able to transfer the station names to train lines -
|
|
||||||
# maybe with polling the station ids to see what train lines come up?
|
|
||||||
api_key,
|
api_key,
|
||||||
["A", "C", "E", "1", "2", "3"],
|
["A", "C", "E", "1", "2", "3"],
|
||||||
["127S", "127N", "A27N", "A27S"]
|
["127S", "127N", "A27N", "A27S"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def mta_callback(routes):
|
||||||
|
global subway_data
|
||||||
|
subway_data = link_to_station(mtaController.convert_routes_to_station_first(routes))
|
||||||
|
|
||||||
|
|
||||||
|
class threadWrapper(threading.Thread):
|
||||||
|
def __init__(self, run):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.run = run
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.run()
|
||||||
|
|
||||||
|
|
||||||
|
def start_mta():
|
||||||
|
mtaController.add_callback(mta_callback)
|
||||||
|
mtaController.start_updates()
|
||||||
|
|
||||||
|
|
||||||
threadLock = threading.Lock()
|
threadLock = threading.Lock()
|
||||||
threads = [threadWrapper(start_mta, mtaController)]
|
threads = [threadWrapper(start_mta)]
|
||||||
|
|
||||||
for t in threads:
|
for t in threads:
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
app.run("0.0.0.0", port=5000, debug=True)
|
app.run(host="localhost", debug=True, port=5000)
|
||||||
# Wait for all threads to complete
|
# Wait for all threads to complete
|
||||||
for t in threads:
|
for t in threads:
|
||||||
t.join()
|
t.join()
|
||||||
|
|||||||
@@ -4,10 +4,20 @@
|
|||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<script src="/static/js/DataRequests.js"></script>
|
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
|
<script src="https://cdn.socket.io/3.1.3/socket.io.min.js"
|
||||||
|
integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-dark-5@1.0.2/dist/css/bootstrap-dark.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-dark-5@1.0.2/dist/css/bootstrap-dark.min.css" rel="stylesheet">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script
|
||||||
|
src="https://code.jquery.com/jquery-3.6.0.min.js"
|
||||||
|
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="/static/js/DataRequests.js"></script>
|
||||||
|
|
||||||
<title>Hello, world!</title>
|
<title>Hello, world!</title>
|
||||||
</head>
|
</head>
|
||||||
@@ -23,18 +33,18 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div>
|
<div id="station_1">
|
||||||
<nav class="navbar navbar-dark bg-dark">
|
<nav class="navbar navbar-dark bg-dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<span class="navbar-brand mb-0 h1 station-name">Navbar</span>
|
<span class="navbar-brand mb-0 h1 station-name">{{station_1}}</span>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton2"
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton2"
|
||||||
data-bs-toggle="dropdown" aria-expanded="false">
|
data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
Dropdown button
|
Select a Station
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
|
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton2">
|
||||||
{% for item in station_names %}
|
{% for item in station_names %}
|
||||||
<li><a class="dropdown-item" href="/get_stop_id/{{ item }}">{{ item }}</a></li>
|
<li><a class="dropdown-item" onclick="javascript:setStation(this)">{{ item }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,18 +61,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
|
<img src="/static/images/lines/A.svg" alt="" width="60" height="60"
|
||||||
<img src="/static/images/lines/1.svg" alt="" width="60" height="60"
|
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4 align-middle">
|
<h1 class="display-4 align-middle">
|
||||||
1, 4, and 5 minutes
|
Pi MTA Display!
|
||||||
</h1>
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<h1 class="display-4">1, 4, and 5 minutes</h1>
|
<img src="/static/images/lines/C.svg" alt="" width="60" height="60"
|
||||||
|
class="align-middle">
|
||||||
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<h1 class="display-4">1 and 5 minutes</h1>
|
<img src="/static/images/lines/E.svg" alt="" width="60" height="60"
|
||||||
|
class="align-middle">
|
||||||
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,22 +93,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
|
<img src="/static/images/lines/A.svg" alt="" width="60" height="60"
|
||||||
<img src="/static/images/lines/1.svg" alt="" width="60" height="60"
|
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4 align-middle">
|
<h1 class="display-4 align-middle">
|
||||||
Pi MTA Display!
|
Pi MTA Display!
|
||||||
</h1>
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<img src="/static/images/lines/2.svg" alt="" width="60" height="60"
|
<img src="/static/images/lines/C.svg" alt="" width="60" height="60"
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4">A second item</h1>
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<img src="/static/images/lines/3.svg" alt="" width="60" height="60"
|
<img src="/static/images/lines/E.svg" alt="" width="60" height="60"
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4">A third item </h1>
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,10 +119,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="station_2">
|
||||||
<nav class="navbar navbar-dark bg-dark">
|
<nav class="navbar navbar-dark bg-dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<span class="navbar-brand mb-0 h1 station-name">Marble Hill-225 St</span>
|
<span class="navbar-brand mb-0 h1 station-name">{{station_2}}</span>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton3"
|
||||||
|
data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
Select a Station
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdownMenuButton3">
|
||||||
|
{% for item in station_names %}
|
||||||
|
<li><a class="dropdown-item" onclick="javascript:setStation(this)">{{ item }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="container-fluid content-row g-0">
|
<div class="container-fluid content-row g-0">
|
||||||
@@ -116,7 +147,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
|
|
||||||
<img src="/static/images/lines/A.svg" alt="" width="60" height="60"
|
<img src="/static/images/lines/A.svg" alt="" width="60" height="60"
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4 align-middle">
|
<h1 class="display-4 align-middle">
|
||||||
@@ -126,12 +156,16 @@
|
|||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<img src="/static/images/lines/C.svg" alt="" width="60" height="60"
|
<img src="/static/images/lines/C.svg" alt="" width="60" height="60"
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4">A second item</h1>
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<img src="/static/images/lines/E.svg" alt="" width="60" height="60"
|
<img src="/static/images/lines/E.svg" alt="" width="60" height="60"
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4">A third item </h1>
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -145,18 +179,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
|
<img src="/static/images/lines/A.svg" alt="" width="60" height="60"
|
||||||
<img src="/static/images/lines/1.svg" alt="" width="60" height="60"
|
|
||||||
class="align-middle">
|
class="align-middle">
|
||||||
<h1 class="display-4 align-middle">
|
<h1 class="display-4 align-middle">
|
||||||
Pi MTA Display!
|
Pi MTA Display!
|
||||||
</h1>
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<h1 class="display-4">A second item</h1>
|
<img src="/static/images/lines/C.svg" alt="" width="60" height="60"
|
||||||
|
class="align-middle">
|
||||||
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item station-info">
|
<li class="list-group-item station-info">
|
||||||
<h1 class="display-4">A third item </h1>
|
<img src="/static/images/lines/E.svg" alt="" width="60" height="60"
|
||||||
|
class="align-middle">
|
||||||
|
<h1 class="display-4">
|
||||||
|
Pi MTA Display!
|
||||||
|
</h1>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -166,8 +207,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Optional JavaScript -->
|
<!-- Optional JavaScript -->
|
||||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
|
|
||||||
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
|
|
||||||
crossorigin="anonymous"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
function clearCanvas() {
|
const interval = setInterval(function () {
|
||||||
var canvas = document.getElementById("inputCanvas");
|
updateData($('#station_1'))
|
||||||
var ctx = canvas.getContext("2d");
|
updateData($('#station_2'))
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
}, 5000);
|
||||||
}
|
|
||||||
|
function updateData(station) {
|
||||||
|
|
||||||
function getData() {
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
//the url where you want to sent the userName and password to
|
//the url where you want to sent the userName and password to
|
||||||
@@ -15,10 +15,10 @@ $(document).ready(function () {
|
|||||||
dataType: "json",
|
dataType: "json",
|
||||||
async: true,
|
async: true,
|
||||||
//json object to sent to the authentication url
|
//json object to sent to the authentication url
|
||||||
data: JSON.stringify({"test_dict":"test_value"}, null, '\t'),
|
data: JSON.stringify({"station": station.find('.station-name:first').get(0).innerText}, null, '\t'),
|
||||||
|
|
||||||
success: function (data, text) {
|
success: function (data, text) {
|
||||||
$("#result").text(JSON.stringify(data));
|
// console.log(data)
|
||||||
|
updateStation(station, data)
|
||||||
},
|
},
|
||||||
error: function (request, status, error) {
|
error: function (request, status, error) {
|
||||||
alert(request.responseText);
|
alert(request.responseText);
|
||||||
@@ -26,8 +26,55 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#test_button").click(function () {
|
function updateStation(station, data) {
|
||||||
getData();
|
//get first item
|
||||||
});
|
updateDirections(station, data, "North");
|
||||||
|
updateDirections(station, data, "South");
|
||||||
|
}
|
||||||
|
|
||||||
});
|
function updateDirections(station, data, direction) {
|
||||||
|
// console.log(direction)
|
||||||
|
// console.log(".card:".concat(direction === "North" ? "first" : "last"))
|
||||||
|
n = data[direction]
|
||||||
|
// console.log(data[direction])
|
||||||
|
list_items = station.find(".card:".concat(direction === "North" ? "first" : "last")).find(".station-info")
|
||||||
|
var i = 0;
|
||||||
|
for (var train in n) {
|
||||||
|
// console.log(train)
|
||||||
|
// console.log(list_items)
|
||||||
|
updateLineItem(list_items.get(i), n[train], train)
|
||||||
|
i = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLineItem(listItem, times, train) {
|
||||||
|
// console.log(times)
|
||||||
|
$(listItem).find("img").attr("src", "/static/images/lines/" + train + ".svg")
|
||||||
|
$(listItem).find("h1").text(times.sort(function (a, b) {
|
||||||
|
return a - b;
|
||||||
|
}).join(", "));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function setStation(ele) {
|
||||||
|
console.log(ele)
|
||||||
|
console.log($(ele).text())
|
||||||
|
var stop_name = ele.text;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
//the url where you want to sent the userName and password to
|
||||||
|
url: '/get_stop_id',
|
||||||
|
contentType: "application/json",
|
||||||
|
dataType: "json",
|
||||||
|
async: true,
|
||||||
|
//json object to sent to the authentication url
|
||||||
|
data: JSON.stringify({"stop_name": stop_name}, null, '\t'),
|
||||||
|
success: function (data, text) {
|
||||||
|
alert(JSON.stringify(data));
|
||||||
|
},
|
||||||
|
error: function (request, status, error) {
|
||||||
|
alert(request.responseText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user