adjusted station information modals, start new chat easily via heard stations

This commit is contained in:
DJ2LS 2024-05-09 22:52:25 +02:00
parent 1cf316cb17
commit 1750565b71
8 changed files with 233 additions and 102 deletions

View file

@ -6,7 +6,9 @@ import chat_conversations from "./chat_conversations.vue";
import chat_messages from "./chat_messages.vue";
import chat_new_message from "./chat_new_message.vue";
import { getStationInfo } from "./../js/api";
import { getStationInfoByCallsign } from "./../js/stationHandler";
import { setActivePinia } from "pinia";
import pinia from "../store/index";
@ -118,67 +120,10 @@ watch(
},
);
const stationInfo = ref({
callsign: "N/A", // Default value for callsign
location: {
gridsquare: "N/A", // Default value for gridsquare
},
});
async function getStationInfoByCallsign() {
try {
const data = await getStationInfo(chat.selectedCallsign);
stationInfo.value = {
callsign: data.callsign || "N/A", // Default if not present
location: {
gridsquare: data.location?.gridsquare || "N/A", // Default if not present
},
};
} catch (error) {
console.error("Error fetching station info:", error);
}
}
</script>
<template>
<!-- Station Info Modal -->
<div
class="modal fade"
ref="modalEle"
id="dxStationInfoModal"
tabindex="-1"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="p-0 m-0">{{ stationInfo.callsign }}</h4>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<p>
<strong>Location:</strong> {{ stationInfo.location.gridsquare }}
</p>
<p><strong>Details:</strong> {{ stationInfo.details }}</p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
<div class="container-fluid d-flex p-0">
<!-- Chat Conversations -->
@ -202,7 +147,8 @@ async function getStationInfoByCallsign() {
class="btn btn-sm btn-outline-secondary ms-2 border-0"
data-bs-target="#dxStationInfoModal"
data-bs-toggle="modal"
@click="getStationInfoByCallsign()"
@click="getStationInfoByCallsign(chat.selectedCallsign)"
disabled
>
<h4 class="p-0 m-0">{{ chat.selectedCallsign }}</h4>
</button>

View file

@ -35,6 +35,13 @@ function newChat() {
if (callsign === "") return;
this.newChatCall.value = "";
}
function startNewChat(){
chat.newChatCallsign = "";
chat.newChatMessage = "Hi there! Nice to meet you!"
}
</script>
<template>
@ -43,6 +50,7 @@ function newChat() {
class="btn btn-outline-primary w-100"
data-bs-target="#newChatModal"
data-bs-toggle="modal"
@click="startNewChat()"
>
<i class="bi bi-pencil-square"> Start a new chat</i>
</button>

View file

@ -11,6 +11,12 @@ import { settingsStore as settings } from "../../store/settingsStore.js";
import { useStateStore } from "../../store/stateStore.js";
const state = useStateStore(pinia);
import { useChatStore } from "../../store/chatStore.js";
const chat = useChatStore(pinia);
import { getStationInfoByCallsign } from "./../../js/stationHandler";
function getDateTime(timestampRaw) {
var datetime = new Date(timestampRaw * 1000).toLocaleString(
navigator.language,
@ -61,6 +67,12 @@ function getActivityInfo(activityType) {
return { iconClass: "", description: activityType };
}
}
function startNewChat(callsign){
chat.newChatCallsign = callsign;
chat.newChatMessage = "Hi there! Nice to meet you!"
}
</script>
<template>
<div class="card h-100">
@ -99,7 +111,26 @@ function getActivityInfo(activityType) {
</td>
<td>{{ item.frequency / 1000 }} kHz</td>
<td>
{{ item.origin }}
<button
class="btn btn-sm btn-outline-secondary ms-2 border-0"
data-bs-target="#dxStationInfoModal"
data-bs-toggle="modal"
@click="getStationInfoByCallsign(item.origin)"
disabled
>
<h6 class="p-0 m-0">{{ item.origin }}</h6>
</button>
<button
class="btn btn-sm border-0 btn-outline-primary"
data-bs-target="#newChatModal"
data-bs-toggle="modal"
@click="startNewChat(item.origin)"
>
<i class="bi bi-pencil-square"></i>
</button>
</td>
<td>
{{ item.gridsquare }}

View file

@ -10,13 +10,19 @@ setActivePinia(pinia);
import { useChatStore } from "../store/chatStore.js";
const chat = useChatStore(pinia);
import { useStationStore } from "../store/stationStore.js";
const station = useStationStore(pinia);
import { useStateStore } from "../store/stateStore.js";
const state = useStateStore(pinia);
import { getStationInfoByCallsign, setStationInfoByCallsign } from "../js/stationHandler.js";
import { settingsStore } from "../store/settingsStore.js";
import { settingsStore as settings, onChange } from "../store/settingsStore.js";
import { sendModemTestFrame, setStationInfo, getStationInfo } from "../js/api";
import { sendModemTestFrame } from "../js/api";
import main_startup_check from "./main_startup_check.vue";
import { newMessage, deleteCallsignFromDB } from "../js/messagesHandler.ts";
@ -118,6 +124,9 @@ const transmissionSpeedChartDataMessageInfo = computed(() => ({
],
}));
/*
const stationInfoData = ref({
name: "",
city: "",
@ -137,53 +146,89 @@ const stationInfoData = ref({
},
comments: "",
});
*/
// Function to handle updates and save changes
function updateStationInfo() {
console.log("Updating station info:", stationInfoData.value);
let mycall = settingsStore.remote.STATION.mycall;
let myssid = settingsStore.remote.STATION.myssid;
let fullCall = `${mycall}-${myssid}`;
setStationInfo(fullCall, stationInfoData.value);
console.log("Updating station info:", fullCall);
setStationInfoByCallsign(fullCall, station.stationInfo.value);
}
// Fixme: this is a dirty hack. Can we make this more VueJS like?
onMounted(() => {
const modalElement = document.getElementById("stationInfoModal");
modalElement.addEventListener("show.bs.modal", fetchStationInfo);
modalElement.addEventListener("show.bs.modal", fetchMyStationInfo);
});
async function fetchStationInfo() {
function fetchMyStationInfo(){
let mycall = settingsStore.remote.STATION.mycall;
let myssid = settingsStore.remote.STATION.myssid;
let fullCall = `${mycall}-${myssid}`;
let result = await getStationInfo(fullCall);
let info = result.info;
stationInfoData.value = {
name: info.name || "",
city: info.city || "",
age: info.age || "",
radio: info.radio || "",
antenna: info.antenna || "",
email: info.email || "",
website: info.website || "",
socialMedia: {
facebook: info.socialMedia.facebook || "",
"twitter-x": info.socialMedia["twitter-x"] || "",
mastodon: info.socialMedia.mastodon || "",
instagram: info.socialMedia.instagram || "",
linkedin: info.socialMedia.linkedin || "",
youtube: info.socialMedia.youtube || "",
tiktok: info.socialMedia.tiktok || "",
},
comments: info.comments || "",
};
getStationInfoByCallsign(fullCall)
}
</script>
<template>
<main_startup_check />
<!-- Station Info Modal -->
<div
class="modal fade"
ref="modalEle"
id="dxStationInfoModal"
tabindex="-1"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="p-0 m-0">{{ station.stationInfo.callsign }}</h4>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<div class="alert alert-primary" role="alert">
<strong> Please note:</strong> This is a preview to show you the
direction, FreeDATA is going somewhen. For now you can save only
your personal data, so we can optimize and improve the database. In
future this data can be requested by a remote station.
</div>
<ul>
<li v-for="(value, key) in station.stationInfo.info" :key="key">
<strong>{{ key }}:</strong> {{ value }}
</li>
</ul>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
<!-- updater release notes-->
<div
class="modal fade"
@ -408,7 +453,9 @@ async function fetchStationInfo() {
<br />
2. Enter a first message
<br />
3. Pressing "START NEW CHAT"
3. Click "START NEW CHAT"
<br />
4. Check the chat tab on left side for messages
</div>
<div class="form-floating mb-3">
@ -1421,7 +1468,7 @@ async function fetchStationInfo() {
type="text"
class="form-control"
placeholder="Name"
v-model="stationInfoData.name"
v-model="station.stationInfo.info.name"
/>
</div>
@ -1434,7 +1481,7 @@ async function fetchStationInfo() {
type="text"
class="form-control"
placeholder="City"
v-model="stationInfoData.city"
v-model="station.stationInfo.info.city"
/>
</div>
@ -1447,7 +1494,7 @@ async function fetchStationInfo() {
type="text"
class="form-control"
placeholder="Age"
v-model="stationInfoData.age"
v-model="station.stationInfo.info.age"
/>
</div>
@ -1460,7 +1507,7 @@ async function fetchStationInfo() {
type="text"
class="form-control"
placeholder="Radio"
v-model="stationInfoData.radio"
v-model="station.stationInfo.info.radio"
/>
</div>
@ -1473,7 +1520,7 @@ async function fetchStationInfo() {
type="text"
class="form-control"
placeholder="Antenna"
v-model="stationInfoData.antenna"
v-model="station.stationInfo.info.antenna"
/>
</div>
@ -1484,7 +1531,7 @@ async function fetchStationInfo() {
type="url"
class="form-control"
placeholder="Website"
v-model="stationInfoData.website"
v-model="station.stationInfo.info.website"
/>
</div>
@ -1497,13 +1544,13 @@ async function fetchStationInfo() {
type="email"
class="form-control"
placeholder="Email"
v-model="stationInfoData.email"
v-model="station.stationInfo.info.email"
/>
</div>
<!-- Social Media Inputs -->
<div class="mb-3">
<div v-for="(url, platform) in stationInfoData.socialMedia">
<div v-for="(url, platform) in station.stationInfo.info.socialMedia">
<div class="input-group mb-1" :key="platform">
<span class="input-group-text"
><i :class="`bi bi-${platform}`"></i
@ -1512,7 +1559,7 @@ async function fetchStationInfo() {
type="url"
class="form-control"
:placeholder="`${platform.charAt(0).toUpperCase() + platform.slice(1)} URL`"
v-model="stationInfoData.socialMedia[platform]"
v-model="station.stationInfo.info.socialMedia[platform]"
/>
</div>
</div>
@ -1526,7 +1573,7 @@ async function fetchStationInfo() {
<textarea
class="form-control"
rows="3"
v-model="stationInfoData.comments"
v-model="station.stationInfo.info.comments"
></textarea>
</div>
</div>

View file

@ -0,0 +1,67 @@
import { useStationStore } from "../store/stationStore.js";
const station = useStationStore();
import { getStationInfo, setStationInfo } from "../js/api";
export async function getStationInfoByCallsign(callsign) {
try {
const result = await getStationInfo(callsign);
console.log(result)
station.stationInfo.callsign = result.callsign || "N/A";
station.stationInfo.location.gridsquare = result.location?.gridsquare || "N/A";
// Check if info is null and assign default values if it is
if (result.info === null) {
station.stationInfo.value.info = {
name: "",
city: "",
age: "",
radio: "",
antenna: "",
email: "",
website: "",
socialMedia: {
facebook: "",
"twitter-x": "",
mastodon: "",
instagram: "",
linkedin: "",
youtube: "",
tiktok: "",
},
comments: "",
};
} else {
station.stationInfo.info = {
name: result.info.name || "",
city: result.info.city || "",
age: result.info.age || "",
radio: result.info.radio || "",
antenna: result.info.antenna || "",
email: result.info.email || "",
website: result.info.website || "",
socialMedia: {
facebook: result.info.socialMedia.facebook || "",
"twitter-x": result.info.socialMedia["twitter-x"] || "",
mastodon: result.info.socialMedia.mastodon || "",
instagram: result.info.socialMedia.instagram || "",
linkedin: result.info.socialMedia.linkedin || "",
youtube: result.info.socialMedia.youtube || "",
tiktok: result.info.socialMedia.tiktok || "",
},
comments: result.info.comments || "",
};
}
} catch (error) {
console.error("Error fetching station info:", error);
}
}
export async function setStationInfoByCallsign(callsign){
console.log(station.stationInfo)
setStationInfo(callsign, station.stationInfo)
}

View file

@ -0,0 +1,33 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import * as bootstrap from "bootstrap";
export const useStationStore = defineStore("stationStore", () => {
const stationInfo = ref({
callsign: "N/A", // Default value for callsign
location: {
gridsquare: "N/A", // Default value for gridsquare
},
info: {
name: "",
city: "",
age: "",
radio: "",
antenna: "",
email: "",
website: "",
socialMedia: {
facebook: "",
"twitter-x": "", // Use twitter-x to correspond to the Twitter X icon
mastodon: "",
instagram: "",
linkedin: "",
youtube: "",
tiktok: "",
},
comments: "",
}
});
return{
stationInfo
}
});

View file

@ -33,7 +33,7 @@ class DatabaseManagerStations(DatabaseManager):
finally:
session.remove()
def update_station(self, callsign, new_info):
def update_station_info(self, callsign, new_info):
"""
Updates the information of a station identified by its callsign.

View file

@ -52,7 +52,6 @@ def set_config():
else:
print(f"Config file '{config_file}' not found. Exiting.")
sys.exit(1)
return config_file
@ -80,7 +79,7 @@ def validate(req, param, validator, isRequired = True):
api_abort(f"Value of '{param}' is invalid.", 400)
# Takes a transmit command and puts it in the transmit command queue
def enqueue_tx_command(cmd_class, params = {}):
def enqueue_tx_command(cmd_class, params={}):
try:
command = cmd_class(app.config_manager.read(), app.state_manager, app.event_manager, params)
app.logger.info(f"Command {command.get_name()} running...")
@ -323,8 +322,8 @@ def get_set_station_info_by_callsign(callsign):
if request.method in ['GET']:
station = DatabaseManagerStations(app.event_manager).get_station(callsign)
return api_response(station)
elif request.method in ['POST']:
result = DatabaseManagerStations(app.event_manager).update_station(callsign, new_info=request.json)
elif request.method in ['POST'] and "info" in request.json:
result = DatabaseManagerStations(app.event_manager).update_station_info(callsign, new_info=request.json["info"])
return api_response(result)
else:
api_abort('Error using endpoint...', 500)