mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-11 02:05:58 +00:00
feat(Map): Added an option to show 'Offline characters' to map admins & managers only
- updated UI layout for map settings modal
This commit is contained in:
@@ -870,3 +870,63 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Map refresh END */
|
/* Map refresh END */
|
||||||
|
|
||||||
|
.inputContainer {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.inputContainer > span:nth-child(1),
|
||||||
|
.inputContainer > label:nth-child(1) {
|
||||||
|
color: var(--gray-200);
|
||||||
|
font-size: 13px;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.inputContainer > :nth-child(2) {
|
||||||
|
border-bottom: 2px dotted #3f3f3f;
|
||||||
|
height: 1px;
|
||||||
|
margin: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallInputSwitch {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.smallInputSwitch .p-inputswitch {
|
||||||
|
height: 1rem;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
.smallInputSwitch .p-inputswitch.p-inputswitch-checked .p-inputswitch-slider::before {
|
||||||
|
transform: translateX(1rem);
|
||||||
|
}
|
||||||
|
.smallInputSwitch .p-inputswitch.p-highlight .p-inputswitch-slider:before {
|
||||||
|
transform: translateX(1rem);
|
||||||
|
}
|
||||||
|
.smallInputSwitch .p-inputswitch .p-inputswitch-slider::before {
|
||||||
|
width: 0.8rem;
|
||||||
|
height: 0.8rem;
|
||||||
|
margin-top: -0.4rem;
|
||||||
|
margin-left: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkboxRoot.sizeXS {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
.checkboxRoot.sizeXS .p-checkbox-box,
|
||||||
|
.checkboxRoot.sizeXS .p-checkbox-input {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
.checkboxRoot.sizeM {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
.checkboxRoot.sizeM .p-checkbox-box,
|
||||||
|
.checkboxRoot.sizeM .p-checkbox-input {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
|
|||||||
import { CharacterCard, LayoutEventBlocker, WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
import { CharacterCard, LayoutEventBlocker, WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
||||||
import { sortCharacters } from '@/hooks/Mapper/components/mapInterface/helpers/sortCharacters.ts';
|
import { sortCharacters } from '@/hooks/Mapper/components/mapInterface/helpers/sortCharacters.ts';
|
||||||
import useLocalStorageState from 'use-local-storage-state';
|
import useLocalStorageState from 'use-local-storage-state';
|
||||||
|
import { useMapCheckPermissions, useMapGetOption } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||||
|
import { UserPermission } from '@/hooks/Mapper/types/permissions.ts';
|
||||||
|
|
||||||
type CharItemProps = {
|
type CharItemProps = {
|
||||||
compact: boolean;
|
compact: boolean;
|
||||||
@@ -62,6 +64,14 @@ export const LocalCharacters = () => {
|
|||||||
|
|
||||||
const [systemId] = selectedSystems;
|
const [systemId] = selectedSystems;
|
||||||
|
|
||||||
|
const restrictOfflineShowing = useMapGetOption('restrict_offline_showing');
|
||||||
|
const isAdminOrManager = useMapCheckPermissions([UserPermission.MANAGE_MAP]);
|
||||||
|
|
||||||
|
const showOffline = useMemo(
|
||||||
|
() => !restrictOfflineShowing || isAdminOrManager,
|
||||||
|
[isAdminOrManager, restrictOfflineShowing],
|
||||||
|
);
|
||||||
|
|
||||||
const itemTemplate = useItemTemplate();
|
const itemTemplate = useItemTemplate();
|
||||||
|
|
||||||
const sorted = useMemo(() => {
|
const sorted = useMemo(() => {
|
||||||
@@ -70,13 +80,13 @@ export const LocalCharacters = () => {
|
|||||||
.map(x => ({ ...x, isOwn: userCharacters.includes(x.eve_id), compact: settings.compact }))
|
.map(x => ({ ...x, isOwn: userCharacters.includes(x.eve_id), compact: settings.compact }))
|
||||||
.sort(sortCharacters);
|
.sort(sortCharacters);
|
||||||
|
|
||||||
if (!settings.showOffline) {
|
if (!showOffline || !settings.showOffline) {
|
||||||
return sorted.filter(c => c.online);
|
return sorted.filter(c => c.online);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sorted;
|
return sorted;
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [characters, settings.showOffline, settings.compact, systemId, userCharacters, presentCharacters]);
|
}, [showOffline, characters, settings.showOffline, settings.compact, systemId, userCharacters, presentCharacters]);
|
||||||
|
|
||||||
const isNobodyHere = sorted.length === 0;
|
const isNobodyHere = sorted.length === 0;
|
||||||
const isNotSelectedSystem = selectedSystems.length !== 1;
|
const isNotSelectedSystem = selectedSystems.length !== 1;
|
||||||
@@ -88,14 +98,16 @@ export const LocalCharacters = () => {
|
|||||||
<div className="flex justify-between items-center text-xs w-full">
|
<div className="flex justify-between items-center text-xs w-full">
|
||||||
<span className="select-none">Local{showList ? ` [${sorted.length}]` : ''}</span>
|
<span className="select-none">Local{showList ? ` [${sorted.length}]` : ''}</span>
|
||||||
<LayoutEventBlocker className="flex items-center gap-2">
|
<LayoutEventBlocker className="flex items-center gap-2">
|
||||||
<WdCheckbox
|
{showOffline && (
|
||||||
size="xs"
|
<WdCheckbox
|
||||||
labelSide="left"
|
size="xs"
|
||||||
label={'Show offline'}
|
labelSide="left"
|
||||||
value={settings.showOffline}
|
label={'Show offline'}
|
||||||
classNameLabel="text-stone-400 hover:text-stone-200 transition duration-300"
|
value={settings.showOffline}
|
||||||
onChange={() => setSettings(() => ({ ...settings, showOffline: !settings.showOffline }))}
|
classNameLabel="text-stone-400 hover:text-stone-200 transition duration-300"
|
||||||
/>
|
onChange={() => setSettings(() => ({ ...settings, showOffline: !settings.showOffline }))}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={clsx('w-4 h-4 cursor-pointer', {
|
className={clsx('w-4 h-4 cursor-pointer', {
|
||||||
@@ -115,7 +127,9 @@ export const LocalCharacters = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{isNobodyHere && !isNotSelectedSystem && (
|
{isNobodyHere && !isNotSelectedSystem && (
|
||||||
<div className="w-full h-full flex justify-center items-center select-none text-stone-400/80 text-sm">Nobody here</div>
|
<div className="w-full h-full flex justify-center items-center select-none text-stone-400/80 text-sm">
|
||||||
|
Nobody here
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showList && (
|
{showList && (
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export const MapSettings = ({ show, onHide }: MapSettingsProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
header="Map settings"
|
header="Map user settings"
|
||||||
visible={show}
|
visible={show}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
style={{ width: '550px' }}
|
style={{ width: '550px' }}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import clsx from 'clsx';
|
|||||||
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
|
import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types';
|
||||||
import { CharacterCard, WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
import { CharacterCard, WdCheckbox } from '@/hooks/Mapper/components/ui-kit';
|
||||||
import useLocalStorageState from 'use-local-storage-state';
|
import useLocalStorageState from 'use-local-storage-state';
|
||||||
|
import { useMapCheckPermissions, useMapGetOption } from '@/hooks/Mapper/mapRootProvider/hooks/api';
|
||||||
|
import { UserPermission } from '@/hooks/Mapper/types/permissions.ts';
|
||||||
|
|
||||||
type WindowLocalSettingsType = {
|
type WindowLocalSettingsType = {
|
||||||
compact: boolean;
|
compact: boolean;
|
||||||
@@ -50,14 +52,22 @@ export const OnTheMap = ({ show, onHide }: OnTheMapProps) => {
|
|||||||
defaultValue: STORED_DEFAULT_VALUES,
|
defaultValue: STORED_DEFAULT_VALUES,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const restrictOfflineShowing = useMapGetOption('restrict_offline_showing');
|
||||||
|
const isAdminOrManager = useMapCheckPermissions([UserPermission.MANAGE_MAP]);
|
||||||
|
|
||||||
|
const showOffline = useMemo(
|
||||||
|
() => !restrictOfflineShowing || isAdminOrManager,
|
||||||
|
[isAdminOrManager, restrictOfflineShowing],
|
||||||
|
);
|
||||||
|
|
||||||
const sorted = useMemo(() => {
|
const sorted = useMemo(() => {
|
||||||
const out = characters.map(x => ({ ...x, isOwn: userCharacters.includes(x.eve_id) })).sort(sortCharacters);
|
const out = characters.map(x => ({ ...x, isOwn: userCharacters.includes(x.eve_id) })).sort(sortCharacters);
|
||||||
if (!settings.hideOffline) {
|
if (showOffline && !settings.hideOffline) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return out.filter(x => x.online);
|
return out.filter(x => x.online);
|
||||||
}, [characters, settings.hideOffline, userCharacters]);
|
}, [showOffline, characters, settings.hideOffline, userCharacters]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
@@ -70,14 +80,16 @@ export const OnTheMap = ({ show, onHide }: OnTheMapProps) => {
|
|||||||
>
|
>
|
||||||
<div className={clsx(classes.SidebarContent, '')}>
|
<div className={clsx(classes.SidebarContent, '')}>
|
||||||
<div className={'flex justify-end items-center gap-2 px-3'}>
|
<div className={'flex justify-end items-center gap-2 px-3'}>
|
||||||
<WdCheckbox
|
{showOffline && (
|
||||||
size="m"
|
<WdCheckbox
|
||||||
labelSide="left"
|
size="m"
|
||||||
label={'Hide offline'}
|
labelSide="left"
|
||||||
value={settings.hideOffline}
|
label={'Hide offline'}
|
||||||
classNameLabel="text-stone-400 hover:text-stone-200 transition duration-300"
|
value={settings.hideOffline}
|
||||||
onChange={() => setSettings(() => ({ ...settings, hideOffline: !settings.hideOffline }))}
|
classNameLabel="text-stone-400 hover:text-stone-200 transition duration-300"
|
||||||
/>
|
onChange={() => setSettings(() => ({ ...settings, hideOffline: !settings.hideOffline }))}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<VirtualScroller
|
<VirtualScroller
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export const RightBar = ({ onShowOnTheMap, onShowMapSettings }: RightBarProps) =
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center mb-2 gap-1">
|
<div className="flex flex-col items-center mb-2 gap-1">
|
||||||
<WdTooltipWrapper content="User settings" position={TooltipPosition.left}>
|
<WdTooltipWrapper content="Map user settings" position={TooltipPosition.left}>
|
||||||
<button
|
<button
|
||||||
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ export const WHClassView = ({
|
|||||||
data: { wormholesData },
|
data: { wormholesData },
|
||||||
} = useMapRootState();
|
} = useMapRootState();
|
||||||
|
|
||||||
console.log(whClassName);
|
|
||||||
|
|
||||||
const whData = useMemo(() => wormholesData[whClassName], [whClassName, wormholesData]);
|
const whData = useMemo(() => wormholesData[whClassName], [whClassName, wormholesData]);
|
||||||
const whClass = useMemo(() => WORMHOLES_ADDITIONAL_INFO[whData.dest], [whData.dest]);
|
const whClass = useMemo(() => WORMHOLES_ADDITIONAL_INFO[whData.dest], [whData.dest]);
|
||||||
const whClassStyle = WORMHOLE_CLASS_STYLES[whClass?.wormholeClassID] ?? '';
|
const whClassStyle = WORMHOLE_CLASS_STYLES[whClass?.wormholeClassID] ?? '';
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const INITIAL_DATA: MapRootData = {
|
|||||||
selectedSystems: [],
|
selectedSystems: [],
|
||||||
selectedConnections: [],
|
selectedConnections: [],
|
||||||
userPermissions: {},
|
userPermissions: {},
|
||||||
|
options: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum InterfaceStoredSettingsProps {
|
export enum InterfaceStoredSettingsProps {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './useMapInit';
|
export * from './useMapInit';
|
||||||
export * from './useMapUpdated';
|
export * from './useMapUpdated';
|
||||||
export * from './useMapCheckPermissions';
|
export * from './useMapCheckPermissions';
|
||||||
|
export * from './useMapGetOption';
|
||||||
export * from './useRoutes';
|
export * from './useRoutes';
|
||||||
export * from './useCommandsConnections';
|
export * from './useCommandsConnections';
|
||||||
export * from './useCommandsSystems';
|
export * from './useCommandsSystems';
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
|
||||||
|
|
||||||
|
export const useMapGetOption = (option: string) => {
|
||||||
|
const {
|
||||||
|
data: { options },
|
||||||
|
} = useMapRootState();
|
||||||
|
|
||||||
|
return useMemo(() => options[option], [option, options]);
|
||||||
|
};
|
||||||
@@ -20,6 +20,7 @@ export const useMapInit = () => {
|
|||||||
present_characters,
|
present_characters,
|
||||||
hubs,
|
hubs,
|
||||||
user_permissions,
|
user_permissions,
|
||||||
|
options,
|
||||||
}: CommandInit) => {
|
}: CommandInit) => {
|
||||||
const updateData: Partial<MapRootData> = {};
|
const updateData: Partial<MapRootData> = {};
|
||||||
|
|
||||||
@@ -60,6 +61,10 @@ export const useMapInit = () => {
|
|||||||
updateData.hubs = hubs;
|
updateData.hubs = hubs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
updateData.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
if (system_static_infos) {
|
if (system_static_infos) {
|
||||||
system_static_infos.forEach(static_info => {
|
system_static_infos.forEach(static_info => {
|
||||||
addSystemStatic(static_info);
|
addSystemStatic(static_info);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export type CommandInit = {
|
|||||||
user_permissions: UserPermissions;
|
user_permissions: UserPermissions;
|
||||||
hubs: string[];
|
hubs: string[];
|
||||||
routes: RoutesList;
|
routes: RoutesList;
|
||||||
|
options: Record<string, string | boolean>;
|
||||||
reset?: boolean;
|
reset?: boolean;
|
||||||
};
|
};
|
||||||
export type CommandAddSystems = SolarSystemRawType[];
|
export type CommandAddSystems = SolarSystemRawType[];
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ export type MapUnionTypes = {
|
|||||||
kills: Record<number, number>;
|
kills: Record<number, number>;
|
||||||
connections: SolarSystemConnection[];
|
connections: SolarSystemConnection[];
|
||||||
userPermissions: Partial<UserPermissions>;
|
userPermissions: Partial<UserPermissions>;
|
||||||
|
options: Record<string, string | boolean>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ defmodule WandererApp.Map do
|
|||||||
hubs: [],
|
hubs: [],
|
||||||
connections: Map.new(),
|
connections: Map.new(),
|
||||||
acls: [],
|
acls: [],
|
||||||
|
options: Map.new(),
|
||||||
characters_limit: nil,
|
characters_limit: nil,
|
||||||
hubs_limit: nil
|
hubs_limit: nil
|
||||||
|
|
||||||
@@ -69,6 +70,9 @@ defmodule WandererApp.Map do
|
|||||||
def get_characters_limit(map_id),
|
def get_characters_limit(map_id),
|
||||||
do: {:ok, map_id |> get_map!() |> Map.get(:characters_limit, 100)}
|
do: {:ok, map_id |> get_map!() |> Map.get(:characters_limit, 100)}
|
||||||
|
|
||||||
|
def get_options(map_id),
|
||||||
|
do: {:ok, map_id |> get_map!() |> Map.get(:options, Map.new())}
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a full list of characters in the map
|
Returns a full list of characters in the map
|
||||||
"""
|
"""
|
||||||
@@ -251,6 +255,13 @@ defmodule WandererApp.Map do
|
|||||||
map
|
map
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_options!(%{map_id: map_id} = map, options) do
|
||||||
|
map_id
|
||||||
|
|> update_map(%{options: options})
|
||||||
|
|
||||||
|
map
|
||||||
|
end
|
||||||
|
|
||||||
def add_systems!(map, []), do: map
|
def add_systems!(map, []), do: map
|
||||||
|
|
||||||
def add_systems!(%{map_id: map_id} = map, [system | rest]) do
|
def add_systems!(%{map_id: map_id} = map, [system | rest]) do
|
||||||
|
|||||||
@@ -277,15 +277,11 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event({:options_updated, options}, state),
|
def handle_event({:options_updated, options}, %{map: map} = state) do
|
||||||
do: %{
|
map |> WandererApp.Map.update_options!(options)
|
||||||
state
|
|
||||||
| map_opts: [
|
%{state | map_opts: map_options(options)}
|
||||||
layout: options |> Map.get("layout", "left_to_right"),
|
end
|
||||||
store_custom_labels:
|
|
||||||
options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
def handle_event({ref, _result}, %{map_id: _map_id} = state) do
|
def handle_event({ref, _result}, %{map_id: _map_id} = state) do
|
||||||
Process.demonitor(ref, [:flush])
|
Process.demonitor(ref, [:flush])
|
||||||
@@ -319,6 +315,16 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
map |> Map.put_new(attribute, get_in(update, [Access.key(attribute)]))
|
map |> Map.put_new(attribute, get_in(update, [Access.key(attribute)]))
|
||||||
end)}
|
end)}
|
||||||
|
|
||||||
|
defp map_options(options) do
|
||||||
|
[
|
||||||
|
layout: options |> Map.get("layout", "left_to_right"),
|
||||||
|
store_custom_labels:
|
||||||
|
options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom(),
|
||||||
|
restrict_offline_showing:
|
||||||
|
options |> Map.get("restrict_offline_showing", "false") |> String.to_existing_atom()
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
defp save_map_state(%{map_id: map_id} = _state) do
|
defp save_map_state(%{map_id: map_id} = _state) do
|
||||||
systems_last_activity =
|
systems_last_activity =
|
||||||
map_id
|
map_id
|
||||||
@@ -389,22 +395,17 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
systems,
|
systems,
|
||||||
connections
|
connections
|
||||||
) do
|
) do
|
||||||
|
{:ok, options} = WandererApp.MapRepo.options_to_form_data(initial_map)
|
||||||
|
|
||||||
map =
|
map =
|
||||||
initial_map
|
initial_map
|
||||||
|> WandererApp.Map.new()
|
|> WandererApp.Map.new()
|
||||||
|
|> WandererApp.Map.update_options!(options)
|
||||||
|> WandererApp.Map.update_subscription_settings!(subscription_settings)
|
|> WandererApp.Map.update_subscription_settings!(subscription_settings)
|
||||||
|> WandererApp.Map.add_systems!(systems)
|
|> WandererApp.Map.add_systems!(systems)
|
||||||
|> WandererApp.Map.add_connections!(connections)
|
|> WandererApp.Map.add_connections!(connections)
|
||||||
|> WandererApp.Map.add_characters!(characters)
|
|> WandererApp.Map.add_characters!(characters)
|
||||||
|
|
||||||
{:ok, map_options} = WandererApp.MapRepo.options_to_form_data(initial_map)
|
|
||||||
|
|
||||||
map_opts = [
|
|
||||||
layout: map_options |> Map.get("layout", "left_to_right"),
|
|
||||||
store_custom_labels:
|
|
||||||
map_options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
|
||||||
]
|
|
||||||
|
|
||||||
character_ids =
|
character_ids =
|
||||||
map_id
|
map_id
|
||||||
|> WandererApp.Map.get_map!()
|
|> WandererApp.Map.get_map!()
|
||||||
@@ -412,7 +413,7 @@ defmodule WandererApp.Map.Server.Impl do
|
|||||||
|
|
||||||
WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids)
|
WandererApp.Cache.insert("map_#{map_id}:invalidate_character_ids", character_ids)
|
||||||
|
|
||||||
%{state | map: map, map_opts: map_opts}
|
%{state | map: map, map_opts: map_options(options)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
def maybe_import_systems(state, %{"systems" => systems} = _settings, user_id, character_id) do
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
defmodule WandererApp.MapRepo do
|
defmodule WandererApp.MapRepo do
|
||||||
use WandererApp, :repository
|
use WandererApp, :repository
|
||||||
|
|
||||||
@default_map_options %{"layout" => "left_to_right", "store_custom_labels" => "false"}
|
@default_map_options %{
|
||||||
|
"layout" => "left_to_right",
|
||||||
|
"store_custom_labels" => "false",
|
||||||
|
"restrict_offline_showing" => "false"
|
||||||
|
}
|
||||||
|
|
||||||
def get(map_id, relationships \\ []) do
|
def get(map_id, relationships \\ []) do
|
||||||
map_id
|
map_id
|
||||||
|
|||||||
@@ -143,15 +143,10 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
def server_status(assigns) do
|
def server_status(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div
|
<div
|
||||||
class="flex flex-col p-4 items-center absolute bottom-16 left-1 gap-2 tooltip tooltip-right"
|
class="flex flex-col p-4 items-center absolute bottom-16 left-2 gap-2 tooltip tooltip-right"
|
||||||
data-tip="server: Tranquility"
|
data-tip="server: Tranquility"
|
||||||
>
|
>
|
||||||
<div
|
<div class={"block w-2 h-2 rounded-full shadow-inner #{if @online, do: " bg-green-500", else: "bg-red-500"}"}>
|
||||||
:if={@online}
|
|
||||||
class="absolute block w-4 h-4 rounded-full shadow-inner bg-green-500 animate-ping"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class={"block w-4 h-4 rounded-full shadow-inner #{if @online, do: " bg-green-500", else: "bg-red-500"}"}>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
@@ -336,6 +331,7 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
"""
|
"""
|
||||||
attr(:id, :any, default: nil)
|
attr(:id, :any, default: nil)
|
||||||
attr(:class, :string, default: nil)
|
attr(:class, :string, default: nil)
|
||||||
|
attr(:wrapper_class, :string, default: nil)
|
||||||
attr(:name, :any)
|
attr(:name, :any)
|
||||||
attr(:label, :string, default: nil)
|
attr(:label, :string, default: nil)
|
||||||
attr(:prefix, :string, default: nil)
|
attr(:prefix, :string, default: nil)
|
||||||
@@ -381,21 +377,62 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name} class="form-control mt-8">
|
<div phx-feedback-for={@name} class="form-control mt-2">
|
||||||
<label class="label cursor-pointer gap-2">
|
<label class="inputContainer" for={@name}>
|
||||||
<span class="label-text"><%= @label %></span>
|
<span><%= @label %></span>
|
||||||
<input type="hidden" name={@name} value="false" />
|
<div></div>
|
||||||
<input
|
<div class="smallInputSwitch">
|
||||||
type="checkbox"
|
<div class="flex items-center">
|
||||||
id={@id}
|
<div
|
||||||
name={@name}
|
class={[
|
||||||
value="true"
|
"checkboxRoot sizeM p-checkbox p-component",
|
||||||
checked={@checked}
|
classes("p-highlight": @checked)
|
||||||
class="checkbox"
|
]}
|
||||||
{@rest}
|
data-p-highlight={@checked}
|
||||||
/>
|
data-p-disabled="false"
|
||||||
|
data-pc-name="checkbox"
|
||||||
|
data-pc-section="root"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id={@id}
|
||||||
|
name={@name}
|
||||||
|
type="checkbox"
|
||||||
|
class="p-checkbox-input"
|
||||||
|
aria-invalid="false"
|
||||||
|
data-pc-section="input"
|
||||||
|
value="true"
|
||||||
|
checked={@checked}
|
||||||
|
{@rest}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="p-checkbox-box"
|
||||||
|
data-p-highlight={@checked}
|
||||||
|
data-p-disabled="false"
|
||||||
|
data-pc-section="box"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
:if={@checked}
|
||||||
|
width="14"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 14 14"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="p-icon p-checkbox-icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
data-pc-section="icon"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M4.86199 11.5948C4.78717 11.5923 4.71366 11.5745 4.64596 11.5426C4.57826 11.5107 4.51779 11.4652 4.46827 11.4091L0.753985 7.69483C0.683167 7.64891 0.623706 7.58751 0.580092 7.51525C0.536478 7.44299 0.509851 7.36177 0.502221 7.27771C0.49459 7.19366 0.506156 7.10897 0.536046 7.03004C0.565935 6.95111 0.613367 6.88 0.674759 6.82208C0.736151 6.76416 0.8099 6.72095 0.890436 6.69571C0.970973 6.67046 1.05619 6.66385 1.13966 6.67635C1.22313 6.68886 1.30266 6.72017 1.37226 6.76792C1.44186 6.81567 1.4997 6.8786 1.54141 6.95197L4.86199 10.2503L12.6397 2.49483C12.7444 2.42694 12.8689 2.39617 12.9932 2.40745C13.1174 2.41873 13.2343 2.47141 13.3251 2.55705C13.4159 2.64268 13.4753 2.75632 13.4938 2.87973C13.5123 3.00315 13.4888 3.1292 13.4271 3.23768L5.2557 11.4091C5.20618 11.4652 5.14571 11.5107 5.07801 11.5426C5.01031 11.5745 4.9368 11.5923 4.86199 11.5948Z"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label for={@name} class="select-none ml-1.5"></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
@@ -403,24 +440,28 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
def input(%{type: "range"} = assigns) do
|
def input(%{type: "range"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
<label class="form-control w-full">
|
<div class="form-control w-full">
|
||||||
<.label for={@id}>
|
<.label for={@id}>
|
||||||
<span class="label-text"><%= @label %></span>
|
<span><%= @label %></span>
|
||||||
<span class="label-value"><%= @value %></span>
|
<div></div>
|
||||||
|
<%= @value %>
|
||||||
</.label>
|
</.label>
|
||||||
<input
|
|
||||||
type="range"
|
<div>
|
||||||
id={@id}
|
<input
|
||||||
name={@name}
|
type="range"
|
||||||
value={@value}
|
id={@id}
|
||||||
class={[
|
name={@name}
|
||||||
"p-component w-full",
|
value={@value}
|
||||||
@class,
|
class={[
|
||||||
@errors != [] && "border-rose-400 focus:border-rose-400"
|
"p-component w-full",
|
||||||
]}
|
@class,
|
||||||
{@rest}
|
@errors != [] && "border-rose-400 focus:border-rose-400"
|
||||||
/>
|
]}
|
||||||
</label>
|
{@rest}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
@@ -428,13 +469,20 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
|
|
||||||
def input(%{type: "select"} = assigns) do
|
def input(%{type: "select"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div
|
||||||
|
phx-feedback-for={@name}
|
||||||
|
class={[
|
||||||
|
"inputContainer",
|
||||||
|
@wrapper_class
|
||||||
|
]}
|
||||||
|
>
|
||||||
<.label :if={@label} for={@id}><%= @label %></.label>
|
<.label :if={@label} for={@id}><%= @label %></.label>
|
||||||
|
<div :if={@label}></div>
|
||||||
<select
|
<select
|
||||||
id={@id}
|
id={@id}
|
||||||
name={@name}
|
name={@name}
|
||||||
class={[
|
class={[
|
||||||
"w-full",
|
"p-component",
|
||||||
@class
|
@class
|
||||||
]}
|
]}
|
||||||
multiple={@multiple}
|
multiple={@multiple}
|
||||||
@@ -503,9 +551,9 @@ defmodule WandererAppWeb.CoreComponents do
|
|||||||
|
|
||||||
def label(assigns) do
|
def label(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div for={@for} class="label">
|
<label for={@for} class="inputContainer">
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</div>
|
</label>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ defmodule WandererAppWeb.MapPicker do
|
|||||||
:if={maps}
|
:if={maps}
|
||||||
type="select"
|
type="select"
|
||||||
field={f[:map_slug]}
|
field={f[:map_slug]}
|
||||||
class="select h-8 min-h-[0px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
placeholder="Select a map..."
|
placeholder="Select a map..."
|
||||||
options={Enum.map(@maps.result, fn map -> {map.label, map.value} end)}
|
options={Enum.map(@maps.result, fn map -> {map.label, map.value} end)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -136,8 +136,10 @@
|
|||||||
<.input
|
<.input
|
||||||
type="select"
|
type="select"
|
||||||
field={f[:owner_id]}
|
field={f[:owner_id]}
|
||||||
class="p-dropdown p-component p-inputwrapper mt-8"
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
placeholder="Select a map owner"
|
wrapper_class="mt-2"
|
||||||
|
label="Owner"
|
||||||
|
placeholder="Select an owner"
|
||||||
options={Enum.map(@characters, fn character -> {character.label, character.id} end)}
|
options={Enum.map(@characters, fn character -> {character.label, character.id} end)}
|
||||||
/>
|
/>
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ defmodule WandererAppWeb.AclMember do
|
|||||||
<.input
|
<.input
|
||||||
type="select"
|
type="select"
|
||||||
field={f[:role]}
|
field={f[:role]}
|
||||||
class="select h-8 min-h-[0px] !pt-1 !pb-1 text-sm bg-neutral-900 w-[70px]"
|
class="select h-8 min-h-[0px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
wrapper_class="w-[60px] mr-16"
|
||||||
placeholder="Select a role..."
|
placeholder="Select a role..."
|
||||||
options={Enum.map(@roles, fn role -> {role.label, role.value} end)}
|
options={Enum.map(@roles, fn role -> {role.label, role.value} end)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -500,13 +500,15 @@ defmodule WandererAppWeb.MapCoreEventHandler do
|
|||||||
{:ok, hubs} = map_id |> WandererApp.Map.list_hubs()
|
{:ok, hubs} = map_id |> WandererApp.Map.list_hubs()
|
||||||
{:ok, connections} = map_id |> WandererApp.Map.list_connections()
|
{:ok, connections} = map_id |> WandererApp.Map.list_connections()
|
||||||
{:ok, systems} = map_id |> WandererApp.Map.list_systems()
|
{:ok, systems} = map_id |> WandererApp.Map.list_systems()
|
||||||
|
{:ok, options} = map_id |> WandererApp.Map.get_options()
|
||||||
|
|
||||||
%{
|
%{
|
||||||
systems:
|
systems:
|
||||||
systems
|
systems
|
||||||
|> Enum.map(fn system -> MapEventHandler.map_ui_system(system, include_static_data?) end),
|
|> Enum.map(fn system -> MapEventHandler.map_ui_system(system, include_static_data?) end),
|
||||||
hubs: hubs,
|
hubs: hubs,
|
||||||
connections: connections |> Enum.map(&MapEventHandler.map_ui_connection/1)
|
connections: connections |> Enum.map(&MapEventHandler.map_ui_connection/1),
|
||||||
|
options: options
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -280,14 +280,17 @@ defmodule WandererAppWeb.MapsLive do
|
|||||||
do:
|
do:
|
||||||
{:noreply,
|
{:noreply,
|
||||||
socket
|
socket
|
||||||
|> assign(:amounts, [
|
|> assign(
|
||||||
%{label: "150M", value: 150_000_000},
|
:amounts,
|
||||||
%{label: "300M", value: 300_000_000},
|
[
|
||||||
%{label: "600M", value: 600_000_000},
|
{"150M", 150_000_000},
|
||||||
%{label: "1.2B", value: 1_200_000_000},
|
{"300M", 300_000_000},
|
||||||
%{label: "2.4B", value: 2_400_000_000},
|
{"600M", 600_000_000},
|
||||||
%{label: "5B", value: 5_000_000_000}
|
{"1.2B", 1_200_000_000},
|
||||||
])
|
{"2.4B", 2_400_000_000},
|
||||||
|
{"5B", 5_000_000_000}
|
||||||
|
]
|
||||||
|
)
|
||||||
|> assign(is_topping_up?: true)}
|
|> assign(is_topping_up?: true)}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
@@ -654,7 +657,7 @@ defmodule WandererAppWeb.MapsLive do
|
|||||||
) do
|
) do
|
||||||
options =
|
options =
|
||||||
options_form
|
options_form
|
||||||
|> Map.take(["layout", "store_custom_labels"])
|
|> Map.take(["layout", "store_custom_labels", "restrict_offline_showing"])
|
||||||
|
|
||||||
{:ok, updated_map} = WandererApp.MapRepo.update_options(map, options)
|
{:ok, updated_map} = WandererApp.MapRepo.update_options(map, options)
|
||||||
|
|
||||||
|
|||||||
@@ -139,14 +139,18 @@
|
|||||||
<.input
|
<.input
|
||||||
type="select"
|
type="select"
|
||||||
field={f[:owner_id]}
|
field={f[:owner_id]}
|
||||||
class="p-dropdown p-component p-inputwrapper mt-8"
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
wrapper_class="mt-2"
|
||||||
|
label="Map owner"
|
||||||
placeholder="Select a map owner"
|
placeholder="Select a map owner"
|
||||||
options={Enum.map(@characters, fn character -> {character.label, character.id} end)}
|
options={Enum.map(@characters, fn character -> {character.label, character.id} end)}
|
||||||
/>
|
/>
|
||||||
<.input
|
<.input
|
||||||
type="select"
|
type="select"
|
||||||
field={f[:scope]}
|
field={f[:scope]}
|
||||||
class="p-dropdown p-component p-inputwrapper mt-8"
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
wrapper_class="mt-2"
|
||||||
|
label="Map scope"
|
||||||
placeholder="Select a map scope"
|
placeholder="Select a map scope"
|
||||||
options={Enum.map(@scopes, fn scope -> {scope, scope} end)}
|
options={Enum.map(@scopes, fn scope -> {scope, scope} end)}
|
||||||
/>
|
/>
|
||||||
@@ -182,203 +186,411 @@
|
|||||||
<.modal
|
<.modal
|
||||||
:if={@live_action in [:settings]}
|
:if={@live_action in [:settings]}
|
||||||
title="Map Settings"
|
title="Map Settings"
|
||||||
class="!w-[800px]"
|
class="!min-w-[700px]"
|
||||||
id="map-settings-modal"
|
id="map-settings-modal"
|
||||||
show
|
show
|
||||||
on_cancel={JS.patch(~p"/maps")}
|
on_cancel={JS.patch(~p"/maps")}
|
||||||
>
|
>
|
||||||
<div role="tablist" class="tabs tabs-bordered">
|
<div class="flex flex-col gap-3">
|
||||||
<a
|
<div class="flex flex-col gap-2">
|
||||||
role="tab"
|
<div class="_verticalTabsContainer_1o01l_2">
|
||||||
phx-click="change_settings_tab"
|
<div class="p-tabview p-component" data-pc-name="tabview" data-pc-section="root">
|
||||||
phx-value-tab="general"
|
<div class="p-tabview-nav-container" data-pc-section="navcontainer">
|
||||||
class={[
|
<div class="p-tabview-nav-content" data-pc-section="navcontent">
|
||||||
"tab",
|
<ul class="p-tabview-nav" role="tablist" data-pc-section="nav">
|
||||||
classes("tab-active": @active_settings_tab == "general")
|
<li
|
||||||
]}
|
class={[
|
||||||
>
|
"p-unselectable-text",
|
||||||
<.icon name="hero-wrench-screwdriver-solid" class="w-4 h-4" /> General
|
classes("p-tabview-selected p-highlight": @active_settings_tab == "general")
|
||||||
</a>
|
]}
|
||||||
<a
|
role="presentation"
|
||||||
role="tab"
|
data-pc-name=""
|
||||||
phx-click="change_settings_tab"
|
data-pc-section="header"
|
||||||
phx-value-tab="import"
|
>
|
||||||
class={[
|
<a
|
||||||
"tab",
|
role="tab"
|
||||||
classes("tab-active": @active_settings_tab == "import")
|
class="p-tabview-nav-link flex p-[10px]"
|
||||||
]}
|
tabindex="0"
|
||||||
>
|
aria-controls="pr_id_330_content"
|
||||||
<.icon name="hero-document-arrow-down-solid" class="w-4 h-4" /> Import/Export
|
aria-selected="true"
|
||||||
</a>
|
aria-disabled="false"
|
||||||
<a
|
data-pc-section="headeraction"
|
||||||
:if={@map_subscriptions_enabled?}
|
phx-click="change_settings_tab"
|
||||||
role="tab"
|
phx-value-tab="general"
|
||||||
phx-click="change_settings_tab"
|
>
|
||||||
phx-value-tab="balance"
|
<span class="p-tabview-title" data-pc-section="headertitle">
|
||||||
class={[
|
<.icon name="hero-wrench-screwdriver-solid" class="w-4 h-4" /> General
|
||||||
"tab",
|
</span>
|
||||||
classes("tab-active": @active_settings_tab == "balance")
|
</a>
|
||||||
]}
|
</li>
|
||||||
>
|
|
||||||
<.icon name="hero-banknotes-solid" class="w-4 h-4" /> Balance
|
<li
|
||||||
</a>
|
:if={@map_subscriptions_enabled?}
|
||||||
<a
|
class={[
|
||||||
:if={@map_subscriptions_enabled?}
|
"p-unselectable-text",
|
||||||
role="tab"
|
classes("p-tabview-selected p-highlight": @active_settings_tab == "balance")
|
||||||
phx-click="change_settings_tab"
|
]}
|
||||||
phx-value-tab="subscription"
|
role="presentation"
|
||||||
class={[
|
data-pc-name=""
|
||||||
"tab",
|
data-pc-section="header"
|
||||||
classes("tab-active": @active_settings_tab == "subscription")
|
>
|
||||||
]}
|
<a
|
||||||
>
|
role="tab"
|
||||||
<.icon name="hero-check-badge-solid" class="w-4 h-4" /> Subscription
|
class="p-tabview-nav-link flex p-[10px]"
|
||||||
</a>
|
tabindex="-1"
|
||||||
</div>
|
aria-controls="pr_id_332_content"
|
||||||
<.header :if={@active_settings_tab == "general"} class="bordered border-1 border-zinc-800">
|
aria-selected="false"
|
||||||
<:actions>
|
aria-disabled="false"
|
||||||
<.form
|
data-pc-section="headeraction"
|
||||||
:let={f}
|
phx-click="change_settings_tab"
|
||||||
:if={assigns |> Map.get(:options_form, false)}
|
phx-value-tab="balance"
|
||||||
for={@options_form}
|
>
|
||||||
phx-change="update_options"
|
<span class="p-tabview-title" data-pc-section="headertitle">
|
||||||
>
|
<.icon name="hero-banknotes-solid" class="w-4 h-4" /> Balance
|
||||||
<div>
|
</span>
|
||||||
<div class="stat-title">Map systems layout</div>
|
</a>
|
||||||
<div class="stat-value text-white">
|
</li>
|
||||||
<.input
|
|
||||||
type="select"
|
<li
|
||||||
field={f[:layout]}
|
:if={@map_subscriptions_enabled?}
|
||||||
class="p-dropdown p-component p-inputwrapper"
|
class={[
|
||||||
placeholder="Map default layout"
|
"p-unselectable-text",
|
||||||
options={@layout_options}
|
classes(
|
||||||
/>
|
"p-tabview-selected p-highlight": @active_settings_tab == "subscription"
|
||||||
|
)
|
||||||
|
]}
|
||||||
|
role="presentation"
|
||||||
|
data-pc-name=""
|
||||||
|
data-pc-section="header"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
role="tab"
|
||||||
|
class="p-tabview-nav-link flex p-[10px]"
|
||||||
|
tabindex="-1"
|
||||||
|
aria-controls="pr_id_334_content"
|
||||||
|
aria-selected="false"
|
||||||
|
aria-disabled="false"
|
||||||
|
data-pc-section="headeraction"
|
||||||
|
phx-click="change_settings_tab"
|
||||||
|
phx-value-tab="subscription"
|
||||||
|
>
|
||||||
|
<span class="p-tabview-title" data-pc-section="headertitle">
|
||||||
|
<.icon name="hero-check-badge-solid" class="w-4 h-4" /> Subscription
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li
|
||||||
|
class={[
|
||||||
|
"p-unselectable-text",
|
||||||
|
classes("p-tabview-selected p-highlight": @active_settings_tab == "import")
|
||||||
|
]}
|
||||||
|
role="presentation"
|
||||||
|
data-pc-name=""
|
||||||
|
data-pc-section="header"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
role="tab"
|
||||||
|
class="p-tabview-nav-link flex p-[10px]"
|
||||||
|
tabindex="-1"
|
||||||
|
aria-controls="pr_id_331_content"
|
||||||
|
aria-selected="false"
|
||||||
|
aria-disabled="false"
|
||||||
|
data-pc-section="headeraction"
|
||||||
|
phx-click="change_settings_tab"
|
||||||
|
phx-value-tab="import"
|
||||||
|
>
|
||||||
|
<span class="p-tabview-title" data-pc-section="headertitle">
|
||||||
|
<.icon name="hero-document-arrow-down-solid" class="w-4 h-4" /> Import/Export
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
aria-hidden="true"
|
||||||
|
role="presentation"
|
||||||
|
class="p-tabview-ink-bar"
|
||||||
|
data-pc-section="inkbar"
|
||||||
|
style="width: 146px; left: 0px;"
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-tabview-panels" data-pc-section="panelcontainer">
|
||||||
|
<div
|
||||||
|
id="pr_id_330_content"
|
||||||
|
class="p-tabview-panel"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="pr_id_33_header_0"
|
||||||
|
data-pc-name=""
|
||||||
|
data-pc-section="content"
|
||||||
|
>
|
||||||
|
<div :if={@active_settings_tab == "general"}>
|
||||||
|
<.form
|
||||||
|
:let={f}
|
||||||
|
:if={assigns |> Map.get(:options_form, false)}
|
||||||
|
for={@options_form}
|
||||||
|
phx-change="update_options"
|
||||||
|
>
|
||||||
|
<.input
|
||||||
|
type="select"
|
||||||
|
field={f[:layout]}
|
||||||
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
label="Map systems layout"
|
||||||
|
placeholder="Map default layout"
|
||||||
|
options={@layout_options}
|
||||||
|
/>
|
||||||
|
<.input
|
||||||
|
type="checkbox"
|
||||||
|
field={f[:store_custom_labels]}
|
||||||
|
label="Store system custom labels"
|
||||||
|
/>
|
||||||
|
<.input
|
||||||
|
type="checkbox"
|
||||||
|
field={f[:restrict_offline_showing]}
|
||||||
|
label="Show offline characters to admins & managers only"
|
||||||
|
/>
|
||||||
|
</.form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :if={@active_settings_tab == "import"}>
|
||||||
|
<.form
|
||||||
|
:if={assigns |> Map.get(:import_form, false)}
|
||||||
|
for={@import_form}
|
||||||
|
phx-change="import"
|
||||||
|
>
|
||||||
|
<div phx-drop-target="{@uploads.settings.ref}">
|
||||||
|
<.live_file_input upload={@uploads.settings} />
|
||||||
|
</div>
|
||||||
|
</.form>
|
||||||
|
<progress :if={@importing} class="progress w-56"></progress>
|
||||||
|
<.button
|
||||||
|
id="export-settings-btn"
|
||||||
|
class="mt-8"
|
||||||
|
type="button"
|
||||||
|
disabled={@importing}
|
||||||
|
phx-hook="DownloadJson"
|
||||||
|
data-name={@map_slug}
|
||||||
|
data-content={Jason.encode!(assigns[:export_settings] || %{})}
|
||||||
|
>
|
||||||
|
<.icon name="hero-document-arrow-down-solid" class="w-4 h-4" /> Export Settings
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :if={@active_settings_tab == "balance"}>
|
||||||
|
<div class="stats w-full bg-primary text-primary-content">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-primary">
|
||||||
|
<.button
|
||||||
|
:if={not @is_topping_up?}
|
||||||
|
class="mt-2"
|
||||||
|
type="button"
|
||||||
|
phx-click="show_topup"
|
||||||
|
>
|
||||||
|
<.icon name="hero-banknotes-solid" class="w-4 h-4" /> Top Up
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
|
<div class="stat-title">Map balance</div>
|
||||||
|
<div class="stat-value text-white">
|
||||||
|
ISK <%= @map_balance
|
||||||
|
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
||||||
|
</div>
|
||||||
|
<div class="stat-actions text-end"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<.form
|
||||||
|
:let={f}
|
||||||
|
:if={@is_topping_up?}
|
||||||
|
for={@topup_form}
|
||||||
|
class="mt-2"
|
||||||
|
phx-change="validate_topup"
|
||||||
|
phx-submit="topup"
|
||||||
|
>
|
||||||
|
<.input
|
||||||
|
type="select"
|
||||||
|
field={f[:amount]}
|
||||||
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
label="Topup amount"
|
||||||
|
placeholder="Select topup amount"
|
||||||
|
options={@amounts}
|
||||||
|
/>
|
||||||
|
<div class="modal-action">
|
||||||
|
<.button class="mt-2" type="button" phx-click="hide_topup">
|
||||||
|
Cancel
|
||||||
|
</.button>
|
||||||
|
<.button class="mt-2" type="submit">
|
||||||
|
Top Up
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
|
</.form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<.table
|
||||||
|
:if={@active_settings_tab == "subscription"}
|
||||||
|
class="!max-h-[300px] !overflow-y-auto"
|
||||||
|
empty_label="No active subscriptions, using alpha plan by default."
|
||||||
|
id="active-subscriptions-tbl"
|
||||||
|
rows={@map_subscriptions}
|
||||||
|
>
|
||||||
|
<:col :let={subscription} label="Subscription Plan">
|
||||||
|
<%= subscription.plan %>
|
||||||
|
</:col>
|
||||||
|
<:col :let={subscription} label="Status">
|
||||||
|
<%= subscription.status %>
|
||||||
|
</:col>
|
||||||
|
<:col :let={subscription} label="Characters Limit">
|
||||||
|
<%= subscription.characters_limit %>
|
||||||
|
</:col>
|
||||||
|
<:col :let={subscription} label="Hubs Limit">
|
||||||
|
<%= subscription.hubs_limit %>
|
||||||
|
</:col>
|
||||||
|
<:col :let={subscription} label="Active Till">
|
||||||
|
<.local_time
|
||||||
|
:if={subscription.active_till}
|
||||||
|
id={"subscription-active-till-#{subscription.id}"}
|
||||||
|
at={subscription.active_till}
|
||||||
|
>
|
||||||
|
<%= subscription.active_till %>
|
||||||
|
</.local_time>
|
||||||
|
</:col>
|
||||||
|
<:col :let={subscription} label="Auto Renew">
|
||||||
|
<%= if subscription.auto_renew?, do: "Yes", else: "No" %>
|
||||||
|
</:col>
|
||||||
|
<:action :let={subscription}>
|
||||||
|
<div class="tooltip tooltip-left" data-tip="Edit subscription">
|
||||||
|
<button
|
||||||
|
:if={subscription.status == :active && subscription.plan != :alpha}
|
||||||
|
phx-click="edit-subscription"
|
||||||
|
phx-value-id={subscription.id}
|
||||||
|
>
|
||||||
|
<.icon name="hero-pencil-square-solid" class="w-4 h-4 hover:text-white" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</:action>
|
||||||
|
<:action :let={subscription}>
|
||||||
|
<div class="tooltip tooltip-left" data-tip="Cancel subscription">
|
||||||
|
<button
|
||||||
|
:if={subscription.status == :active && subscription.plan != :alpha}
|
||||||
|
phx-click="cancel-subscription"
|
||||||
|
phx-value-id={subscription.id}
|
||||||
|
data={[confirm: "Please confirm to cancel subscription!"]}
|
||||||
|
>
|
||||||
|
<.icon name="hero-trash-solid" class="w-4 h-4 hover:text-white" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</:action>
|
||||||
|
</.table>
|
||||||
|
|
||||||
|
<.header
|
||||||
|
:if={@active_settings_tab == "subscription" && @is_adding_subscription?}
|
||||||
|
class="bordered border-1 flex flex-col gap-4"
|
||||||
|
>
|
||||||
|
<div :if={is_nil(@selected_subscription)}>
|
||||||
|
Add subscription
|
||||||
|
<div class="badge badge-secondary">Limited time offer: 50%</div>
|
||||||
|
</div>
|
||||||
|
<div :if={not is_nil(@selected_subscription)}>
|
||||||
|
Edit subscription
|
||||||
|
<div class="badge badge-secondary">Limited time offer: 50%</div>
|
||||||
|
</div>
|
||||||
|
<.form
|
||||||
|
:let={f}
|
||||||
|
for={@subscription_form}
|
||||||
|
phx-change="validate_subscription"
|
||||||
|
phx-submit={
|
||||||
|
if is_nil(@selected_subscription),
|
||||||
|
do: "subscribe",
|
||||||
|
else: "update_subscription"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<.input
|
||||||
|
:if={is_nil(@selected_subscription)}
|
||||||
|
type="select"
|
||||||
|
field={f[:period]}
|
||||||
|
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
|
||||||
|
label="Subscription period"
|
||||||
|
options={@subscription_periods}
|
||||||
|
/>
|
||||||
|
<.input
|
||||||
|
field={f[:characters_limit]}
|
||||||
|
label="Characters limit"
|
||||||
|
show_value={true}
|
||||||
|
type="range"
|
||||||
|
min="300"
|
||||||
|
max="5000"
|
||||||
|
step="100"
|
||||||
|
class="range range-xs"
|
||||||
|
/>
|
||||||
|
<.input
|
||||||
|
field={f[:hubs_limit]}
|
||||||
|
label="Hubs limit"
|
||||||
|
show_value={true}
|
||||||
|
type="range"
|
||||||
|
min="20"
|
||||||
|
max="50"
|
||||||
|
step="10"
|
||||||
|
class="range range-xs"
|
||||||
|
/>
|
||||||
|
<.input field={f[:auto_renew?]} label="Auto Renew" type="checkbox" />
|
||||||
|
<div
|
||||||
|
:if={is_nil(@selected_subscription)}
|
||||||
|
class="stats w-full bg-primary text-primary-content mt-2"
|
||||||
|
>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-primary">
|
||||||
|
<.button type="submit">
|
||||||
|
Subscribe
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-8">
|
||||||
|
<div>
|
||||||
|
<div class="stat-title">Estimated price</div>
|
||||||
|
<div class="stat-value text-white">
|
||||||
|
ISK <%= (@estimated_price - @discount)
|
||||||
|
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="stat-title">Discount</div>
|
||||||
|
<div class="stat-value text-white relative">
|
||||||
|
ISK <%= @discount
|
||||||
|
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
||||||
|
<span class="absolute top-0 right-0 text-xs text-white discount" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:if={not is_nil(@selected_subscription)}
|
||||||
|
class="stats w-full bg-primary text-primary-content"
|
||||||
|
>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-figure text-primary">
|
||||||
|
<.button type="button" phx-click="cancel_edit_subscription">
|
||||||
|
Cancel
|
||||||
|
</.button>
|
||||||
|
<.button type="submit">
|
||||||
|
Update
|
||||||
|
</.button>
|
||||||
|
</div>
|
||||||
|
<div class="stat-title">Additional price (mounthly)</div>
|
||||||
|
<div class="stat-value text-white">
|
||||||
|
ISK <%= @additional_price
|
||||||
|
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
||||||
|
</div>
|
||||||
|
<div class="stat-actions text-end"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</.form>
|
||||||
|
</.header>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<.input
|
|
||||||
type="checkbox"
|
|
||||||
field={f[:store_custom_labels]}
|
|
||||||
label="Store system custom labels"
|
|
||||||
/>
|
|
||||||
</.form>
|
|
||||||
</:actions>
|
|
||||||
</.header>
|
|
||||||
<.header :if={@active_settings_tab == "import"} class="bordered border-1 border-zinc-800">
|
|
||||||
Import/Export Map Settings
|
|
||||||
<:actions>
|
|
||||||
<.form :if={assigns |> Map.get(:import_form, false)} for={@import_form} phx-change="import">
|
|
||||||
<div phx-drop-target="{@uploads.settings.ref}">
|
|
||||||
<.live_file_input upload={@uploads.settings} />
|
|
||||||
</div>
|
|
||||||
</.form>
|
|
||||||
<progress :if={@importing} class="progress w-56"></progress>
|
|
||||||
<.button
|
|
||||||
id="export-settings-btn"
|
|
||||||
class="mt-8"
|
|
||||||
type="button"
|
|
||||||
disabled={@importing}
|
|
||||||
phx-hook="DownloadJson"
|
|
||||||
data-name={@map_slug}
|
|
||||||
data-content={Jason.encode!(assigns[:export_settings] || %{})}
|
|
||||||
>
|
|
||||||
<.icon name="hero-document-arrow-down-solid" class="w-4 h-4" /> Export Settings
|
|
||||||
</.button>
|
|
||||||
</:actions>
|
|
||||||
</.header>
|
|
||||||
<.header :if={@active_settings_tab == "balance"} class="bordered border-1 border-zinc-800">
|
|
||||||
<div class="stats w-full bg-primary text-primary-content">
|
|
||||||
<div class="stat">
|
|
||||||
<div class="stat-figure text-primary">
|
|
||||||
<.button :if={not @is_topping_up?} class="mt-2" type="button" phx-click="show_topup">
|
|
||||||
<.icon name="hero-banknotes-solid" class="w-4 h-4" /> Top Up
|
|
||||||
</.button>
|
|
||||||
</div>
|
|
||||||
<div class="stat-title">Map balance</div>
|
|
||||||
<div class="stat-value text-white">
|
|
||||||
ISK <%= @map_balance |> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
|
||||||
</div>
|
|
||||||
<div class="stat-actions text-end"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<.form
|
|
||||||
:let={f}
|
|
||||||
:if={@is_topping_up?}
|
|
||||||
for={@topup_form}
|
|
||||||
phx-change="validate_topup"
|
|
||||||
phx-submit="topup"
|
|
||||||
>
|
|
||||||
<.live_select
|
|
||||||
field={f[:amount]}
|
|
||||||
update_min_len={0}
|
|
||||||
options={@amounts}
|
|
||||||
placeholder="Select topup amount"
|
|
||||||
/>
|
|
||||||
<div class="modal-action">
|
|
||||||
<.button class="mt-2" type="button" phx-click="hide_topup">
|
|
||||||
Cancel
|
|
||||||
</.button>
|
|
||||||
<.button class="mt-2" type="submit">
|
|
||||||
Top Up
|
|
||||||
</.button>
|
|
||||||
</div>
|
|
||||||
</.form>
|
|
||||||
</.header>
|
|
||||||
<.table
|
|
||||||
:if={@active_settings_tab == "subscription"}
|
|
||||||
class="!max-h-[20vh] !overflow-y-auto"
|
|
||||||
empty_label="No active subscriptions, using alpha plan by default."
|
|
||||||
id="active-subscriptions-tbl"
|
|
||||||
rows={@map_subscriptions}
|
|
||||||
>
|
|
||||||
<:col :let={subscription} label="Subscription Plan">
|
|
||||||
<%= subscription.plan %>
|
|
||||||
</:col>
|
|
||||||
<:col :let={subscription} label="Status">
|
|
||||||
<%= subscription.status %>
|
|
||||||
</:col>
|
|
||||||
<:col :let={subscription} label="Characters Limit">
|
|
||||||
<%= subscription.characters_limit %>
|
|
||||||
</:col>
|
|
||||||
<:col :let={subscription} label="Hubs Limit">
|
|
||||||
<%= subscription.hubs_limit %>
|
|
||||||
</:col>
|
|
||||||
<:col :let={subscription} label="Active Till">
|
|
||||||
<.local_time
|
|
||||||
:if={subscription.active_till}
|
|
||||||
id={"subscription-active-till-#{subscription.id}"}
|
|
||||||
at={subscription.active_till}
|
|
||||||
>
|
|
||||||
<%= subscription.active_till %>
|
|
||||||
</.local_time>
|
|
||||||
</:col>
|
|
||||||
<:col :let={subscription} label="Auto Renew">
|
|
||||||
<%= if subscription.auto_renew?, do: "Yes", else: "No" %>
|
|
||||||
</:col>
|
|
||||||
<:action :let={subscription}>
|
|
||||||
<div class="tooltip tooltip-left" data-tip="Edit subscription">
|
|
||||||
<button
|
|
||||||
:if={subscription.status == :active && subscription.plan != :alpha}
|
|
||||||
phx-click="edit-subscription"
|
|
||||||
phx-value-id={subscription.id}
|
|
||||||
>
|
|
||||||
<.icon name="hero-pencil-square-solid" class="w-4 h-4 hover:text-white" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</:action>
|
|
||||||
<:action :let={subscription}>
|
|
||||||
<div class="tooltip tooltip-left" data-tip="Cancel subscription">
|
|
||||||
<button
|
|
||||||
:if={subscription.status == :active && subscription.plan != :alpha}
|
|
||||||
phx-click="cancel-subscription"
|
|
||||||
phx-value-id={subscription.id}
|
|
||||||
data={[confirm: "Please confirm to cancel subscription!"]}
|
|
||||||
>
|
|
||||||
<.icon name="hero-trash-solid" class="w-4 h-4 hover:text-white" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</:action>
|
|
||||||
</.table>
|
|
||||||
|
|
||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<div
|
<div
|
||||||
@@ -402,102 +614,4 @@
|
|||||||
</.button>
|
</.button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<.header
|
|
||||||
:if={@active_settings_tab == "subscription" && @is_adding_subscription?}
|
|
||||||
class="bordered border-1 flex flex-col gap-4"
|
|
||||||
>
|
|
||||||
<div :if={is_nil(@selected_subscription)}>
|
|
||||||
Add subscription
|
|
||||||
<div class="badge badge-secondary">Limited time offer: 50%</div>
|
|
||||||
</div>
|
|
||||||
<div :if={not is_nil(@selected_subscription)}>
|
|
||||||
Edit subscription
|
|
||||||
<div class="badge badge-secondary">Limited time offer: 50%</div>
|
|
||||||
</div>
|
|
||||||
<.form
|
|
||||||
:let={f}
|
|
||||||
for={@subscription_form}
|
|
||||||
phx-change="validate_subscription"
|
|
||||||
phx-submit={if is_nil(@selected_subscription), do: "subscribe", else: "update_subscription"}
|
|
||||||
>
|
|
||||||
<.input
|
|
||||||
:if={is_nil(@selected_subscription)}
|
|
||||||
type="select"
|
|
||||||
field={f[:period]}
|
|
||||||
class="p-dropdown p-component p-inputwrapper"
|
|
||||||
placeholder="Subscription period"
|
|
||||||
options={@subscription_periods}
|
|
||||||
/>
|
|
||||||
<.input
|
|
||||||
field={f[:characters_limit]}
|
|
||||||
label="Characters limit"
|
|
||||||
show_value={true}
|
|
||||||
type="range"
|
|
||||||
min="300"
|
|
||||||
max="5000"
|
|
||||||
step="100"
|
|
||||||
class="range range-xs"
|
|
||||||
/>
|
|
||||||
<.input
|
|
||||||
field={f[:hubs_limit]}
|
|
||||||
label="Hubs limit"
|
|
||||||
show_value={true}
|
|
||||||
type="range"
|
|
||||||
min="20"
|
|
||||||
max="50"
|
|
||||||
step="10"
|
|
||||||
class="range range-xs"
|
|
||||||
/>
|
|
||||||
<.input field={f[:auto_renew?]} label="Auto Renew" type="checkbox" />
|
|
||||||
<div
|
|
||||||
:if={is_nil(@selected_subscription)}
|
|
||||||
class="stats w-full bg-primary text-primary-content"
|
|
||||||
>
|
|
||||||
<div class="stat">
|
|
||||||
<div class="stat-figure text-primary">
|
|
||||||
<.button type="submit">
|
|
||||||
Subscribe
|
|
||||||
</.button>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-8">
|
|
||||||
<div>
|
|
||||||
<div class="stat-title">Estimated price</div>
|
|
||||||
<div class="stat-value text-white">
|
|
||||||
ISK <%= (@estimated_price - @discount)
|
|
||||||
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="stat-title">Discount</div>
|
|
||||||
<div class="stat-value text-white relative">
|
|
||||||
ISK <%= @discount |> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
|
||||||
<span class="absolute top-0 right-0 text-xs text-white discount" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
:if={not is_nil(@selected_subscription)}
|
|
||||||
class="stats w-full bg-primary text-primary-content"
|
|
||||||
>
|
|
||||||
<div class="stat">
|
|
||||||
<div class="stat-figure text-primary">
|
|
||||||
<.button type="button" phx-click="cancel_edit_subscription">
|
|
||||||
Cancel
|
|
||||||
</.button>
|
|
||||||
<.button type="submit">
|
|
||||||
Update
|
|
||||||
</.button>
|
|
||||||
</div>
|
|
||||||
<div class="stat-title">Additional price (mounthly)</div>
|
|
||||||
<div class="stat-value text-white">
|
|
||||||
ISK <%= @additional_price |> Number.to_human(units: ["", "K", "M", "B", "T", "P"]) %>
|
|
||||||
</div>
|
|
||||||
<div class="stat-actions text-end"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</.form>
|
|
||||||
</.header>
|
|
||||||
</.modal>
|
</.modal>
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
31,6,Shuttle,0,0,0,0,0,1
|
31,6,Shuttle,0,0,0,0,0,1
|
||||||
32,1,Alliance,None,0,0,0,0,0
|
32,1,Alliance,None,0,0,0,0,0
|
||||||
38,7,Shield Extender,82,0,0,0,0,1
|
38,7,Shield Extender,82,0,0,0,0,1
|
||||||
39,7,Shield Recharger,83,0,0,0,0,1
|
39,7,Shield Recharger,26451,0,0,0,0,1
|
||||||
40,7,Shield Booster,84,0,0,0,0,1
|
40,7,Shield Booster,84,0,0,0,0,1
|
||||||
41,7,Remote Shield Booster,86,0,0,0,0,1
|
41,7,Remote Shield Booster,86,0,0,0,0,1
|
||||||
43,7,Capacitor Recharger,90,0,0,0,0,1
|
43,7,Capacitor Recharger,26457,0,0,0,0,1
|
||||||
46,7,Propulsion Module,96,0,0,0,0,1
|
46,7,Propulsion Module,96,0,0,0,0,1
|
||||||
47,7,Cargo Scanner,106,0,0,0,0,1
|
47,7,Cargo Scanner,106,0,0,0,0,1
|
||||||
48,7,Ship Scanner,107,0,0,0,0,1
|
48,7,Ship Scanner,107,0,0,0,0,1
|
||||||
@@ -44,8 +44,8 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
54,7,Mining Laser,138,0,0,0,0,1
|
54,7,Mining Laser,138,0,0,0,0,1
|
||||||
55,7,Projectile Weapon,384,0,0,0,0,1
|
55,7,Projectile Weapon,384,0,0,0,0,1
|
||||||
56,7,Missile Launcher,168,0,0,0,0,0
|
56,7,Missile Launcher,168,0,0,0,0,0
|
||||||
57,7,Shield Power Relay,0,0,0,0,0,1
|
57,7,Shield Power Relay,26450,0,0,0,0,1
|
||||||
59,7,Gyrostabilizer,0,0,0,0,0,1
|
59,7,Gyrostabilizer,26452,0,0,0,0,1
|
||||||
60,7,Damage Control,0,0,0,0,0,1
|
60,7,Damage Control,0,0,0,0,0,1
|
||||||
61,7,Capacitor Battery,0,0,0,0,0,1
|
61,7,Capacitor Battery,0,0,0,0,0,1
|
||||||
62,7,Armor Repair Unit,0,1,0,0,0,1
|
62,7,Armor Repair Unit,0,1,0,0,0,1
|
||||||
@@ -86,10 +86,10 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
110,9,Titan Blueprint,None,1,0,0,0,1
|
110,9,Titan Blueprint,None,1,0,0,0,1
|
||||||
111,9,Shuttle Blueprint,0,1,0,0,0,1
|
111,9,Shuttle Blueprint,0,1,0,0,0,1
|
||||||
118,9,Shield Extender Blueprint,82,1,0,0,0,1
|
118,9,Shield Extender Blueprint,82,1,0,0,0,1
|
||||||
119,9,Shield Recharger Blueprint,83,1,0,0,0,1
|
119,9,Shield Recharger Blueprint,26451,1,0,0,0,1
|
||||||
120,9,Shield Booster Blueprint,84,1,0,0,0,1
|
120,9,Shield Booster Blueprint,84,1,0,0,0,1
|
||||||
121,9,Remote Shield Booster Blueprint,86,1,0,0,0,1
|
121,9,Remote Shield Booster Blueprint,86,1,0,0,0,1
|
||||||
123,9,Capacitor Recharger Blueprint,90,1,0,0,0,1
|
123,9,Capacitor Recharger Blueprint,26457,1,0,0,0,1
|
||||||
126,9,Propulsion Module Blueprint,96,1,0,0,0,1
|
126,9,Propulsion Module Blueprint,96,1,0,0,0,1
|
||||||
127,9,Cargo Scanner Blueprint,106,1,0,0,0,1
|
127,9,Cargo Scanner Blueprint,106,1,0,0,0,1
|
||||||
128,9,Ship Scanner Blueprint,107,1,0,0,0,1
|
128,9,Ship Scanner Blueprint,107,1,0,0,0,1
|
||||||
@@ -149,14 +149,14 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
201,7,ECM,0,0,0,0,0,1
|
201,7,ECM,0,0,0,0,0,1
|
||||||
202,7,ECCM,0,0,0,0,0,1
|
202,7,ECCM,0,0,0,0,0,1
|
||||||
203,7,Sensor Backup Array,0,0,0,0,0,1
|
203,7,Sensor Backup Array,0,0,0,0,0,1
|
||||||
205,7,Heat Sink,0,0,0,0,0,1
|
205,7,Heat Sink,26453,0,0,0,0,1
|
||||||
208,7,Sensor Dampener,105,0,0,0,0,1
|
208,7,Sensor Dampener,105,0,0,0,0,1
|
||||||
209,7,Remote Tracking Computer,3346,0,0,0,0,1
|
209,7,Remote Tracking Computer,3346,0,0,0,0,1
|
||||||
210,7,Signal Amplifier,0,0,0,0,0,1
|
210,7,Signal Amplifier,0,0,0,0,0,1
|
||||||
211,7,Tracking Enhancer,0,0,0,0,0,1
|
211,7,Tracking Enhancer,0,0,0,0,0,1
|
||||||
212,7,Sensor Booster,74,0,0,0,0,1
|
212,7,Sensor Booster,74,0,0,0,0,1
|
||||||
213,7,Tracking Computer,3346,0,0,0,0,1
|
213,7,Tracking Computer,3346,0,0,0,0,1
|
||||||
218,9,Heat Sink Blueprint,0,1,0,0,0,1
|
218,9,Heat Sink Blueprint,26453,1,0,0,0,1
|
||||||
223,9,Sensor Booster Blueprint,0,1,0,0,0,1
|
223,9,Sensor Booster Blueprint,0,1,0,0,0,1
|
||||||
224,9,Tracking Computer Blueprint,0,1,0,0,0,1
|
224,9,Tracking Computer Blueprint,0,1,0,0,0,1
|
||||||
225,7,Cheat Module Group,0,0,0,0,0,0
|
225,7,Cheat Module Group,0,0,0,0,0,0
|
||||||
@@ -197,7 +197,7 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
299,18,Repair Drone,0,0,0,0,0,0
|
299,18,Repair Drone,0,0,0,0,0,0
|
||||||
300,20,Cyberimplant,0,1,0,0,0,1
|
300,20,Cyberimplant,0,1,0,0,0,1
|
||||||
301,11,Concord Drone,0,0,0,0,0,0
|
301,11,Concord Drone,0,0,0,0,0,0
|
||||||
302,7,Magnetic Field Stabilizer,0,0,0,0,0,1
|
302,7,Magnetic Field Stabilizer,26454,0,0,0,0,1
|
||||||
303,20,Booster,0,0,0,0,0,1
|
303,20,Booster,0,0,0,0,0,1
|
||||||
304,20,DNA Mutator,0,0,0,0,0,0
|
304,20,DNA Mutator,0,0,0,0,0,0
|
||||||
305,2,Comet,0,0,0,0,0,0
|
305,2,Comet,0,0,0,0,0,0
|
||||||
@@ -595,10 +595,10 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
764,7,Overdrive Injector System,0,0,0,0,0,1
|
764,7,Overdrive Injector System,0,0,0,0,0,1
|
||||||
765,7,Expanded Cargohold,0,0,0,0,0,1
|
765,7,Expanded Cargohold,0,0,0,0,0,1
|
||||||
766,7,Power Diagnostic System,0,0,0,0,0,1
|
766,7,Power Diagnostic System,0,0,0,0,0,1
|
||||||
767,7,Capacitor Power Relay,0,0,0,0,0,1
|
767,7,Capacitor Power Relay,26455,0,0,0,0,1
|
||||||
768,7,Capacitor Flux Coil,0,0,0,0,0,1
|
768,7,Capacitor Flux Coil,26456,0,0,0,0,1
|
||||||
769,7,Reactor Control Unit,0,0,0,0,0,1
|
769,7,Reactor Control Unit,0,0,0,0,0,1
|
||||||
770,7,Shield Flux Coil,0,0,0,0,0,1
|
770,7,Shield Flux Coil,26449,0,0,0,0,1
|
||||||
771,7,Missile Launcher Heavy Assault,3241,0,0,0,0,1
|
771,7,Missile Launcher Heavy Assault,3241,0,0,0,0,1
|
||||||
772,8,Heavy Assault Missile,3237,0,0,0,1,1
|
772,8,Heavy Assault Missile,3237,0,0,0,1,1
|
||||||
773,7,Rig Armor,0,0,0,0,0,1
|
773,7,Rig Armor,0,0,0,0,0,1
|
||||||
@@ -1322,7 +1322,7 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
1962,66,Structure QA Modules,None,0,0,0,0,0
|
1962,66,Structure QA Modules,None,0,0,0,0,0
|
||||||
1964,17,Mutaplasmids,None,0,0,0,0,1
|
1964,17,Mutaplasmids,None,0,0,0,0,1
|
||||||
1966,66,Structure Capacitor Battery,None,0,0,0,0,1
|
1966,66,Structure Capacitor Battery,None,0,0,0,0,1
|
||||||
1967,66,Structure Capacitor Power Relay,None,0,0,0,0,1
|
1967,66,Structure Capacitor Power Relay,26455,0,0,0,0,1
|
||||||
1968,66,Structure Armor Reinforcer,None,0,0,0,0,1
|
1968,66,Structure Armor Reinforcer,None,0,0,0,0,1
|
||||||
1969,7,Abyssal Modules,None,0,0,0,0,0
|
1969,7,Abyssal Modules,None,0,0,0,0,0
|
||||||
1971,2,Abyssal Hazards,None,0,0,0,0,0
|
1971,2,Abyssal Hazards,None,0,0,0,0,0
|
||||||
@@ -1523,6 +1523,12 @@ groupID,categoryID,groupName,iconID,useBasePrice,anchored,anchorable,fittableNon
|
|||||||
4802,11,Asteroid Sansha's Nation Officer Frigate,None,0,0,0,0,0
|
4802,11,Asteroid Sansha's Nation Officer Frigate,None,0,0,0,0,0
|
||||||
4803,11,Asteroid Serpentis Officer Cruiser,None,0,0,0,0,0
|
4803,11,Asteroid Serpentis Officer Cruiser,None,0,0,0,0,0
|
||||||
4804,11,Asteroid Serpentis Officer Frigate,None,0,0,0,0,0
|
4804,11,Asteroid Serpentis Officer Frigate,None,0,0,0,0,0
|
||||||
|
4807,7,Breacher Pod Launchers,None,0,0,0,0,1
|
||||||
|
4808,8,SCARAB Breacher Pods,None,0,0,0,1,1
|
||||||
|
4810,22,Mercenary Den,None,0,0,0,0,1
|
||||||
|
4811,9,Mercenary Den Blueprint,None,1,0,0,0,1
|
||||||
|
4820,9,Mutaplasmid Blueprint,None,1,0,0,0,1
|
||||||
|
4821,17,Atavum,None,1,0,0,0,1
|
||||||
350858,350001,Infantry Weapons,None,1,0,0,0,0
|
350858,350001,Infantry Weapons,None,1,0,0,0,0
|
||||||
351064,350001,Infantry Dropsuits,None,1,0,0,0,0
|
351064,350001,Infantry Dropsuits,None,1,0,0,0,0
|
||||||
351121,350001,Infantry Modules,None,1,0,0,0,0
|
351121,350001,Infantry Modules,None,1,0,0,0,0
|
||||||
|
|||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user