mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-10 17:55:43 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05c3d20e56 | ||
|
|
4633d26517 | ||
|
|
30b0556d47 | ||
|
|
e094378dc5 | ||
|
|
0c48189503 | ||
|
|
a5c346627a | ||
|
|
4e526040bf | ||
|
|
869c25cd60 | ||
|
|
6aac698cd8 | ||
|
|
230016b90f |
37
CHANGELOG.md
37
CHANGELOG.md
@@ -2,6 +2,43 @@
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.43.4](https://github.com/wanderer-industries/wanderer/compare/v1.43.3...v1.43.4) (2025-01-21)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* improve structure widget styling (#127)
|
||||
|
||||
## [v1.43.3](https://github.com/wanderer-industries/wanderer/compare/v1.43.2...v1.43.3) (2025-01-21)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.43.2](https://github.com/wanderer-industries/wanderer/compare/v1.43.1...v1.43.2) (2025-01-21)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* prevent constraint error for follow/toggle (#132)
|
||||
|
||||
## [v1.43.1](https://github.com/wanderer-industries/wanderer/compare/v1.43.0...v1.43.1) (2025-01-20)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.43.0](https://github.com/wanderer-industries/wanderer/compare/v1.42.5...v1.43.0) (2025-01-20)
|
||||
|
||||
|
||||
|
||||
|
||||
### Features:
|
||||
|
||||
* add news post for structures widget (#131)
|
||||
|
||||
## [v1.42.5](https://github.com/wanderer-industries/wanderer/compare/v1.42.4...v1.42.5) (2025-01-20)
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,11 @@ export const SystemStructures: React.FC = () => {
|
||||
<WdImgButton
|
||||
className={`${PrimeIcons.CLOCK} text-sky-400 hover:text-sky-200 transition duration-300`}
|
||||
onClick={handlePasteTimer}
|
||||
tooltip={{
|
||||
position: TooltipPosition.left,
|
||||
// @ts-ignore
|
||||
content: 'Add Structures/Timer',
|
||||
}}
|
||||
/>
|
||||
<WdImgButton
|
||||
className={PrimeIcons.QUESTION_CIRCLE}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
.TableRowCompact {
|
||||
height: 8px;
|
||||
max-height: 8px;
|
||||
font-size: 12px !important;
|
||||
line-height: 8px;
|
||||
}
|
||||
|
||||
.Table {
|
||||
font-size: 12px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.TableRowCompact {
|
||||
height: 8px;
|
||||
max-height: 8px;
|
||||
font-size: 12px !important;
|
||||
line-height: 8px;
|
||||
}
|
||||
|
||||
.Tooltip {
|
||||
white-space: pre-line; // or pre-wrap
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
|
||||
.Table {
|
||||
font-size: 12px;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.Table .p-datatable-tbody > tr > td {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.Tooltip {
|
||||
white-space: pre-line;
|
||||
line-height: 1.2rem;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ export const SystemStructuresContent: React.FC<SystemStructuresContentProps> = (
|
||||
size="small"
|
||||
sortMode="single"
|
||||
rowHover
|
||||
style={{ tableLayout: 'fixed', width: '100%' }}
|
||||
onRowClick={handleRowClick}
|
||||
onRowDoubleClick={handleRowDoubleClick}
|
||||
rowClassName={rowData => {
|
||||
@@ -74,11 +75,56 @@ export const SystemStructuresContent: React.FC<SystemStructuresContentProps> = (
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Column header="Type" body={renderTypeCell} style={{ width: '160px' }} />
|
||||
<Column field="name" header="Name" style={{ width: '120px' }} />
|
||||
<Column header="Owner" body={renderOwnerCell} style={{ width: '120px' }} />
|
||||
<Column field="status" header="Status" style={{ width: '100px' }} />
|
||||
<Column header="Timer" body={renderTimerCell} style={{ width: '110px' }} />
|
||||
<Column
|
||||
header="Type"
|
||||
body={renderTypeCell}
|
||||
style={{
|
||||
width: '160px',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
field="name"
|
||||
header="Name"
|
||||
style={{
|
||||
width: '120px',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
header="Owner"
|
||||
body={renderOwnerCell}
|
||||
style={{
|
||||
width: '120px',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
field="status"
|
||||
header="Status"
|
||||
style={{
|
||||
width: '100px',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
header="Timer"
|
||||
body={renderTimerCell}
|
||||
style={{
|
||||
width: '110px',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
<Column
|
||||
body={(rowData: StructureItem) => (
|
||||
<i
|
||||
@@ -90,7 +136,13 @@ export const SystemStructuresContent: React.FC<SystemStructuresContentProps> = (
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
style={{ width: '40px', textAlign: 'center' }}
|
||||
style={{
|
||||
width: '40px',
|
||||
textAlign: 'center',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
}}
|
||||
/>
|
||||
</DataTable>
|
||||
</div>
|
||||
|
||||
BIN
assets/static/images/news/01-20-structure-widget/cover.png
Executable file
BIN
assets/static/images/news/01-20-structure-widget/cover.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
assets/static/images/news/01-20-structure-widget/enable-widget.png
Executable file
BIN
assets/static/images/news/01-20-structure-widget/enable-widget.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -213,7 +213,7 @@ defmodule WandererAppWeb.MapCharactersEventHandler do
|
||||
s.character_id in user_char_ids
|
||||
end)
|
||||
|
||||
existing = Enum.find(my_settings, &(&1.character_id == clicked_char_id))
|
||||
existing = Enum.find(all_settings, &(&1.character_id == clicked_char_id))
|
||||
|
||||
{:ok, target_setting} =
|
||||
if not is_nil(existing) do
|
||||
|
||||
@@ -270,6 +270,8 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
current_user.characters |> Enum.map(& &1.id)
|
||||
)
|
||||
|
||||
{:ok, map_user_settings} = WandererApp.MapUserSettingsRepo.get(map_id, current_user.id)
|
||||
|
||||
{:ok, character_settings} =
|
||||
case WandererApp.MapCharacterSettingsRepo.get_all_by_map(map_id) do
|
||||
{:ok, settings} -> {:ok, settings}
|
||||
@@ -302,6 +304,7 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
socket
|
||||
|> assign(
|
||||
map_id: map_id,
|
||||
map_user_settings: map_user_settings,
|
||||
page_title: map_name,
|
||||
user_permissions: user_permissions,
|
||||
tracked_character_ids: tracked_character_ids,
|
||||
@@ -334,7 +337,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
} = socket
|
||||
) do
|
||||
with {:ok, _} <- current_user |> WandererApp.Api.User.update_last_map(%{last_map_id: map_id}),
|
||||
{:ok, map_user_settings} <- WandererApp.MapUserSettingsRepo.get(map_id, current_user.id),
|
||||
{:ok, tracked_map_characters} <-
|
||||
WandererApp.Maps.get_tracked_map_characters(map_id, current_user),
|
||||
{:ok, characters_limit} <- map_id |> WandererApp.Map.get_characters_limit(),
|
||||
@@ -414,7 +416,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
socket
|
||||
|> map_start(%{
|
||||
map_id: map_id,
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data,
|
||||
events: events
|
||||
@@ -437,7 +438,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
socket,
|
||||
%{
|
||||
map_id: map_id,
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
initial_data: initial_data,
|
||||
events: events
|
||||
@@ -468,7 +468,6 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
||||
socket
|
||||
|> assign(
|
||||
map_loaded?: true,
|
||||
map_user_settings: map_user_settings,
|
||||
user_characters: user_character_eve_ids,
|
||||
has_tracked_characters?: has_tracked_characters?
|
||||
)
|
||||
|
||||
2
mix.exs
2
mix.exs
@@ -3,7 +3,7 @@ defmodule WandererApp.MixProject do
|
||||
|
||||
@source_url "https://github.com/wanderer-industries/wanderer"
|
||||
|
||||
@version "1.42.5"
|
||||
@version "1.43.4"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
||||
151
priv/posts/2025/01-20-structure-widget.md
Normal file
151
priv/posts/2025/01-20-structure-widget.md
Normal file
@@ -0,0 +1,151 @@
|
||||
%{
|
||||
title: "Managing Upwell Structures & Timers with the Structures Widget",
|
||||
author: "Wanderer Team",
|
||||
cover_image_uri: "/images/news/01-20-structure-widget/cover.png",
|
||||
tags: ~w(interface guide map structures),
|
||||
description: "Learn how to track structure information using the Structures Widget."
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
### Introduction
|
||||
|
||||
Upwell structures like **Astrahus**, **Athanor**, and more are key strategic points in EVE Online. Staying informed about their statuses—whether they’re anchoring, powered, or reinforced—helps you plan defenses, coordinate attacks, and align with allies. Our **Structures Widget** simplifies the process by allowing you to:
|
||||
|
||||
- Copy structure information directly from the in-game Directional Scanner (`D-Scan`) and paste it into the widget.
|
||||
- Keep track of **anchoring** or **reinforced** timers, including exact vulnerability windows.
|
||||
- Share real-time data across the map with your corporation or alliance, ensuring everyone is on the same page.
|
||||
|
||||
In this guide, we’ll explore how to enable the Structures Widget, manage structure data, and make use of the built-in API for remote structure updates.
|
||||
|
||||
---
|
||||
|
||||
### 1. Enabling the Structure Widget
|
||||
|
||||

|
||||
|
||||
1. **Open the Map:**
|
||||
2. **Locate the Widget Settings:** By default, the structure widget panel is not visible. Enable it by going to menu -> map settings -> widgets.
|
||||
3. **Add the Structures Widget:** Click the checkbox for **Structures** from the list of available widgets.
|
||||
|
||||
> **Tip:** Rearrange your widgets by dragging them around the panel to suit your workflow.
|
||||
|
||||
---
|
||||
|
||||
### 2. Overview of the Structures Widget
|
||||
|
||||

|
||||
|
||||
Once enabled, the **Structures Widget** appears in the map. It shows:
|
||||
|
||||
- **Structure Type** (Astrahus, Fortizar, etc.)
|
||||
- **Structure Name** (auto-detected if you paste from D-Scan)
|
||||
- **Owner** (Corporation ticker)
|
||||
- **Status** (Powered, Anchoring, Low Power, Reinforced, etc.)
|
||||
- **Timer** (Reinforced or anchoring end time)
|
||||
|
||||
You can **click** or **double-click** on an entry to edit details like the structure’s owner or add notes about the structure’s purpose or location.
|
||||
|
||||
---
|
||||
|
||||
### 3. Adding Structures via Copy & Paste
|
||||
|
||||
A fast way to add structure data is by copying from in-game D-Scan or show-info panels:
|
||||
|
||||
1. **In EVE Online:** Open the D-Scan window or structure context menu, select the relevant lines of text, and press **Ctrl + C**.
|
||||
2. **In the Widget:** Focus on the Structures Widget, click in the widget area, and press **Ctrl + V** to paste or use the **blue** add structure info button.
|
||||
3. The widget automatically parses the structure names and types. You can also add owners and notes manually.
|
||||
|
||||
This eliminates manual typing and reduces the chance of errors, especially useful when scanning multiple systems.
|
||||
|
||||
---
|
||||
|
||||
### 4. Tracking Reinforced Timers
|
||||
|
||||
When a structure is in a **Reinforced** or **Anchoring** state, we have a timer to note when it becomes vulnerable or completes anchoring:
|
||||
|
||||
- **Timer Field:** If the structure’s status is set to “Reinforced” or “Anchoring,” the widget enables a **Calendar** pop-up where you can set the _end time_.
|
||||
|
||||
Keep your fleet prepared by referencing this schedule. When the timer hits zero, the structure becomes vulnerable (or finishes anchoring).
|
||||
|
||||
---
|
||||
|
||||
### 5. Editing and Deleting Structures
|
||||
|
||||
1. **Single-click** a structure entry to select it.
|
||||
2. Press **Delete** (or **Backspace**) to remove it entirely—useful when clearing out old data or removing outdated structures.
|
||||
3. **Double-click** to open the **Edit Dialog**:
|
||||
- Change **Name**, **Owner**, or **Status**.
|
||||
- Update or remove **Reinforced** timers.
|
||||
- Add or edit **Notes**.
|
||||
|
||||
Any changes made here are immediately visible to other map users.
|
||||
|
||||
---
|
||||
|
||||
### 6. API Integration for Automated Timers
|
||||
|
||||
Beyond the in-app widget, there is a dedicated API endpoint to fetch or update structure timers programmatically. This allows advanced users and third-party applications to seamlessly incorporate structure data.
|
||||
|
||||
**Example API Request/Response**:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
|
||||
"https://wanderer.yourdomain.space/api/map/structure-timers?slug=yourmap"
|
||||
|
||||
"data": [
|
||||
{
|
||||
"name": "Overlook Hotel",
|
||||
"status": "Reinforced",
|
||||
"notes": null,
|
||||
"owner_id": null,
|
||||
"solar_system_id": 31000515,
|
||||
"solar_system_name": "J114942",
|
||||
"character_eve_id": "2122839817",
|
||||
"system_id": "4865aec4-b69d-4524-91d3-250b0556322b",
|
||||
"end_time": "2025-01-22T23:42:03.000000Z",
|
||||
"owner_name": null,
|
||||
"owner_ticker": null,
|
||||
"structure_type": "Astrahus",
|
||||
"structure_type_id": "35832"
|
||||
},
|
||||
{
|
||||
"name": "Some Structure",
|
||||
"status": "Reinforced",
|
||||
"notes": null,
|
||||
"owner_id": null,
|
||||
"solar_system_id": 3100229,
|
||||
"solar_system_name": "somecustomname",
|
||||
"character_eve_id": "some name",
|
||||
"system_id": "ae779ed6-92b3-4349-899d-f1bdf299082f",
|
||||
"end_time": "2025-01-16T03:04:00.000000Z",
|
||||
"owner_name": null,
|
||||
"owner_ticker": null,
|
||||
"structure_type": "Athanor",
|
||||
"structure_type_id": "35835"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
With this API, you could, for example, build automated pings on Slack/Discord when timers are about to expire or display status updates on a custom web dashboard.
|
||||
|
||||
> **Note:** Ensure your API token (`Bearer YOUR_API_TOKEN`) matches the api key generated for you map.
|
||||
|
||||
---
|
||||
|
||||
### 7. Best Practices & Tips
|
||||
|
||||
- **Keep Data Fresh:** Update timers as soon as possible after a structure enters reinforcement. This keeps your corporation or alliance fully informed.
|
||||
- **Use Notes Effectively:** Add details such as final reinforcement phases or relevant system intel (e.g., known hostiles, safe spots) to help allies plan more effectively.
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The **Structures Widget** is your central hub for monitoring, updating, and sharing information about Upwell structures across New Eden. From real-time timer tracking to simple copy-and-paste integration with D-Scan, this widget streamlines group operations and cuts down on manual data entry.
|
||||
|
||||
Whether you’re a solo explorer managing a personal citadel network or a fleet commander overseeing multiple staging systems, the Structures Widget and its accompanying API ensure you’ll always have up-to-date intel on the structures that matter most.
|
||||
|
||||
Fly safe,
|
||||
**The Wanderer Team**
|
||||
Reference in New Issue
Block a user