Compare commits

...

No commits in common. "main" and "feature/wpf_client_part_5" have entirely different histories.

155 changed files with 18315 additions and 2 deletions

436
.gitignore vendored Normal file
View File

@ -0,0 +1,436 @@
Skip to content
Pull requests
Issues
Codespaces
Marketplace
Explore
@danielschick
github /
gitignore
Public
Fork your own copy of github/gitignore
Code
Pull requests 371
Actions
Security
Insights
Beta Try the new code view
gitignore/VisualStudio.gitignore
@n0099
n0099 [VisualStudio.gitignore] remove a trailing space
Latest commit 491040e Jan 26, 2022
History
165 contributors
@shiftkey
@arcresu
@aroben
@bbodenmiller
@HassanHashemi
@haacked
@niik
@AArnott
@sayedihashimi
@saschanaz
@bdougie
@OsirisTerje
398 lines (319 sloc) 6.7 KB
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
# *.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "src/server/BreCal",
"FLASK_DEBUG": "1",
"SECRET_KEY" : "zdiTz8P3jXOc7jztIQAoelK4zztyuCpJ" // https://randomkeygen.com/
},
"args": [
"run" //,
// "--no-debugger",
//"--no-reload"
],
"jinja": true,
"justMyCode": true
}
]
}

View File

@ -1,2 +1,23 @@
# brecal
Bremen calling
# Bremen Calling
___
Projekt zur verbesserten Kommunikation der maritimen Partner bei Schiffsanläufen in Bremen.
## Anforderungen
## Architektur
Die Architektur besteht aus einer Datenbank und einem in Python implementierten Backend, das eine API zu Verfügung stellt. Diese API ist als OpenAPI 3.0 spezifiziert.
Die Anwendung selbst kommuniziert nur über diese API mit der Datenbank. Es sind damit unterschiedliche Anwendungsplattformen denkbar, etwa eine Web-, Mobile- oder Windows Desktop Anwendung.
In dieser [Folie](docs/Architektur.pptx) ist ein Bild / Überblick enthalten.
Ein erster Gedanke des Datenbank-Layouts sieht folgendermaßen aus:
![image](docs/datenbank.jpeg)
## Entwicklung
### Postman
Zum Debuggen der Flask App verwende ich dieses Tutorial:
https://code.visualstudio.com/docs/python/tutorial-flask#_create-a-project-environment-for-the-flask-tutorial

Binary file not shown.

BIN
docs/AMPELKONZEPT_V1.docx Normal file

Binary file not shown.

BIN
docs/Ablaufplan.pptx Normal file

Binary file not shown.

BIN
docs/Arbeitspakete.xlsx Normal file

Binary file not shown.

BIN
docs/Architektur.pptx Normal file

Binary file not shown.

BIN
docs/BremenCalling.pptx Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/Gesamtansicht.pptx Normal file

Binary file not shown.

BIN
docs/UserStories.xlsx Normal file

Binary file not shown.

BIN
docs/datenbank.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,422 @@
{
"info": {
"_postman_id": "9242b2d1-196b-4b2e-af57-c0e9eb141dba",
"name": "BreCal",
"description": "Bremen Calling relevant API calls",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "10427908"
},
"item": [
{
"name": "Login user",
"event": [
{
"listen": "test",
"script": {
"exec": [
"let responseData = pm.response.json();\r",
"pm.environment.set(\"LOGON_TOKEN\", responseData.token)\r",
"console.log(\"Id: \" + responseData.id)"
],
"type": "text/javascript"
}
}
],
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"username\" : \"Londo\",\r\n \"password\" : \"Hallowach\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{SCHEMA}}{{PATH}}/login",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"login"
]
}
},
"response": []
},
{
"name": "Participant GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/participants",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"participants"
]
}
},
"response": []
},
{
"name": "Shipcalls GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/shipcalls",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"shipcalls"
]
}
},
"response": []
},
{
"name": "Shipcalls POST",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"ship_id\" : 1,\r\n \"type\" : 1,\r\n \"eta\" : \"2023-07-23T07:18:19\",\r\n \"voyage\" : \"43B\",\r\n \"tug_required\" : false,\r\n \"pilot_required\" : true,\r\n \"flags\" : 0,\r\n \"pier_side\" : false,\r\n \"bunkering\" : true,\r\n \"recommended_tugs\" : 2\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{SCHEMA}}{{PATH}}/shipcalls",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"shipcalls"
]
}
},
"response": []
},
{
"name": "Shipcalls PUT",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"id\" : 2, \r\n \"recommended_tugs\" : 3\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{SCHEMA}}{{PATH}}/shipcalls",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"shipcalls"
]
}
},
"response": []
},
{
"name": "Berths GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/berths",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"berths"
]
}
},
"response": []
},
{
"name": "Notifications GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/notifications?participant_id=1",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"notifications"
],
"query": [
{
"key": "participant_id",
"value": "1"
}
]
}
},
"response": []
},
{
"name": "Ships GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/ships",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"ships"
]
}
},
"response": []
},
{
"name": "Times GET",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/times?shipcall_id=3",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"times"
],
"query": [
{
"key": "shipcall_id",
"value": "3"
}
]
}
},
"response": []
},
{
"name": "Times POST",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"start_planned\" : \"2023-04-18T07:18:19\",\r\n \"end_planned\" : \"2023-04-18T09:18:19\", \r\n \"shipcall_id\" : 1,\r\n \"participant_id\" : 1\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{SCHEMA}}{{PATH}}/times",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"times"
]
}
},
"response": []
},
{
"name": "Times PUT",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"start_planned\" : \"2023-05-18T07:18:19\",\r\n \"end_planned\" : \"2023-05-18T09:18:19\", \r\n \"id\" : 1\r\n}"
},
"url": {
"raw": "{{SCHEMA}}{{PATH}}/times",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"times"
]
}
},
"response": []
},
{
"name": "Times DELETE",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{LOGON_TOKEN}}",
"type": "string"
}
]
},
"method": "DELETE",
"header": [],
"url": {
"raw": "{{SCHEMA}}{{PATH}}/times?id=3",
"host": [
"{{SCHEMA}}{{PATH}}"
],
"path": [
"times"
],
"query": [
{
"key": "id",
"value": "3"
}
]
}
},
"response": []
}
],
"auth": {
"type": "bearer"
},
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
}
]
}

7383
misc/BreCalApi.cs Normal file

File diff suppressed because it is too large Load Diff

729
misc/BreCalApi.yaml Normal file
View File

@ -0,0 +1,729 @@
openapi: "3.0.0"
info:
version: "0.3.0"
title: "Bremen calling API"
description: Administer DEBRE ship calls, times and notifications
termsOfService: "https://www.bsmd.de/" # url to terms page
contact:
name: "Bremen calling API"
url: "https://www.textbausteine.net"
email: "info@textbausteine.net"
license:
name: "Use at your own risk"
url: "https://www.bsmd.de/license"
servers:
# tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html
- url: "https://brecal.bsmd-emswe.eu/"
description: "Test server hosted on vcup"
paths:
# tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step4_paths_object.html
/login:
post:
summary: Returns a JWT session token and user data if successful
requestBody:
description: Login credentials
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/credentials"
responses:
200:
description: Successful response
content:
application/json:
schema:
$ref: "#/components/schemas/login_result"
400:
$ref: "#/components/responses/400"
403:
$ref: "#/components/responses/403"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/user:
put:
summary: Update user details (first/last name, phone, password)
requestBody:
description: User details
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/user_details"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/shipcalls:
get:
summary: Gets a list of ship calls
#parameters:
# - name: participant_id
# in: query
# required: true
# description: "**Id of participant**. *Example: 2*. Id of participant entity requesting ship calls"
# schema:
# type: integer
responses:
200:
description: ship call list
content:
application/json:
schema:
$ref: "#/components/schemas/shipcalls"
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
post:
summary: Create a new ship call
requestBody:
description: Creates a new ship call. **Do not** provide id parameter.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/shipcall"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
put:
summary: Updates a ship call
requestBody:
description: Creates a new ship call. The id parameter is **required**.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/shipcall"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/ships:
get:
summary: gets a list of registered shipcalls
responses:
200:
description: list of ships
content:
application/json:
schema:
$ref: "#/components/schemas/ship_list"
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/participants:
get:
summary: gets a particular participant entry corresponding to user id
parameters:
- name: user_id
in: query
required: false
description: "**Id of user**. *Example: 2*. User id returned by verify call."
schema:
type: integer
responses:
200:
description: ship call list
content:
application/json:
schema:
$ref: "#/components/schemas/participant_list"
400:
$ref: "#/components/responses/400"
404:
$ref: "#/components/responses/404"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/times:
get:
summary: Get all recorded times for a a ship call
parameters:
- name: shipcall_id
in: query
description: "**Id**. *Example: 42*. Id of referenced ship call."
schema:
type: integer
responses:
200:
description: list of recorded times
content:
application/json:
schema:
$ref: "#/components/schemas/times_list"
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
post:
summary: Create a new times entry for a ship call
requestBody:
description: Times entry that will be added to the ship call. **Do not** provide id parameter.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/times"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
put:
summary: Update a times entry for a ship call
requestBody:
description: Times entry that will be added to the ship call. The id parameter is **required**.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/times"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
delete:
summary: Delete a times entry for a ship call.
parameters:
- name: id
in: query
required: true
schema:
$ref: "#/components/schemas/timesId"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/notifications:
get:
summary: Gets a list of notifications pursuant to a specified participant and ship call
parameters:
- name: participant_id
in: query
required: true
description: "**Id of participant**. *Example: 2*. Id returned through loading of participant"
schema:
type: integer
- name: shipcall_id
in: query
required: true
description: "**Id of ship call**. *Example: 52*. Id given in ship call list"
schema:
$ref: "#/components/schemas/shipcallId"
responses:
200:
description: notification list
content:
application/json:
schema:
$ref: "#/components/schemas/notification"
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/berths:
get:
summary: Gets a list of all berths registered
responses:
200:
description: list of berths
content:
application/json:
schema:
$ref: "#/components/schemas/berth_list"
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
components:
schemas:
credentials:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
format: password
timesId:
description: The unique identifier for a times entry
type: integer
shipcallId:
description: The unique identifier of a ship call
type: integer
shipcall:
type: object
required:
- id
- ship_id
- type
- eta
properties:
id:
$ref: "#/components/schemas/shipcallId"
ship_id:
type: integer
type:
type: integer
# TODO: use an enum
eta:
type: string
format: date-time
voyage:
type: string
maxLength: 16
nullable: true
etd:
type: string
format: date-time
nullable: true
arrival_berth_id:
type: integer
nullable: true
departure_berth_id:
type: integer
nullable: true
tug_required:
type: boolean
nullable: true
pilot_required:
type: boolean
nullable: true
flags:
type: integer
nullable: true
pier_side:
type: boolean
nullable: true
bunkering:
type: boolean
nullable: true
replenishing_terminal:
type: boolean
nullable: true
replenishing_lock:
type: boolean
nullable: true
draft:
type: number
format: float
nullable: true
tidal_window_from:
type: string
format: date-time
nullable: true
tidal_window_to:
type: string
format: date-time
nullable: true
rain_sensitive_cargo:
type: boolean
nullable: true
recommended_tugs:
type: integer
nullable: true
anchored:
type: boolean
nullable: true
moored_lock:
type: boolean
nullable: true
canceled:
type: boolean
nullable: true
participants:
type: array
items:
type: integer
example: [1, 5, 7]
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
shipcalls:
type: array
items:
$ref: "#/components/schemas/shipcall"
times:
type: object
description: the id parameter needs to be missing on POST and to be present on PUT (Update) calls, otherwise a 400 response will be generated
required:
- shipcall_id
- participant_id
properties:
id:
type: integer
eta_berth:
type: string
format: date-time
nullable: true
eta_berth_fixed:
type: boolean
nullable: true
etd_berth:
type: string
format: date-time
nullable: true
etd_berth_fixed:
type: boolean
nullable: true
lock_time:
type: string
format: date-time
nullable: true
lock_time_fixed:
type: boolean
nullable: true
zone_entry:
type: string
format: date-time
nullable: true
zone_entry_fixed:
type: boolean
nullable: true
operations_start:
type: string
format: date-time
nullable: true
operations_end:
type: string
format: date-time
nullable: true
remarks:
type: string
maxLength: 512
nullable: true
shipcall_id:
type: integer
participant_id:
type: integer
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
times_list:
type: array
items:
$ref: "#/components/schemas/times"
berth:
type: object
description: Ship berth used for a ship call
properties:
id:
type: integer
name:
type: string
maxLength: 128
participant_id:
type: integer
nullable: true
lock:
type: boolean
nullable: true
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
deleted:
type: boolean
default: false
berth_list:
type: array
items:
$ref: "#/components/schemas/berth"
ship:
type: object
description: a ship
properties:
id:
type: integer
name:
type: string
maxLength: 64
imo:
type: integer
nullable: true
callsign:
type: string
maxLength: 8
nullable: true
participant_id:
type: integer
nullable: true
length:
type: number
format: float
nullable: true
width:
type: number
format: float
nullable: true
is_tug:
type: boolean
default: false
bollard_pull:
type: integer
nullable: true
eni:
type: integer
nullable: true
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
deleted:
type: boolean
default: false
ship_list:
type: array
items:
$ref: "#/components/schemas/ship"
notification:
type: object
description: a notification created by the engine if a times entry violates a rule
properties:
id:
type: integer
times_id:
type: integer
participant_id:
type: integer
notification_type:
type: string
enum: [undefined, email, push]
timestamp:
type: string
format: date-time
acknowledged:
type: boolean
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
notification_list:
type: array
items:
$ref: "#/components/schemas/notification"
participant:
type: object
description: A organisational entity that participates in Bremen Calling
properties:
id:
type: integer
name:
type: string
maxLength: 128
street:
type: string
maxLength: 128
postal code:
type: string
maxLength: 5
city:
type: string
maxLength: 64
type:
type: integer
created:
type: string
format: date-time
modified:
type: string
format: date-time
nullable: true
deleted:
type: boolean
default: false
participant_list:
type: array
items:
$ref: "#/components/schemas/participant"
login_result:
type: object
description: result structure of a successful login attempt
properties:
id:
type: integer
participant_id:
type: integer
first_name:
type: string
last_name:
type: string
user_name:
type: string
user_phone:
type: string
exp:
type: number
format: float
token:
type: string
user_details:
type: object
description: fields that a user may change
properties:
id:
type: integer
old_password:
type: string
nullable: true
new_password:
type: string
nullable: true
first_name:
type: string
nullable: true
last_name:
type: string
nullable: true
user_phone:
type: string
nullable: true
Error:
type: object
required:
- message
properties:
message:
description: A human readable error message
type: string
securitySchemes:
ApiKey:
type: apiKey
in: header
name: Authorization
responses:
400:
description: Invalid input
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
401:
description: Not authorized
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
500:
description: Unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
503:
description: Not available
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
security:
- ApiKey: []
externalDocs:
url: http://textbausteine.net/
description: Extra documentation and conditions for Bremen Calling

50
misc/Readme.md Normal file
View File

@ -0,0 +1,50 @@
# Database Bremen Calling
## Server
mariadb v 10
## Getting started
- Execute 'create_schema.sql' and import 'sample_data.sql'
If the database is updated or changed, please update these files.
To avoid errors, it is best to drop the entire database, edit the create script and re-import the sample data.
## Creating the dump file
```bash
mysqldump -u [username] -p --no-create-info --complete-insert bremen_calling > sample_data.sql
```
## Removing existing tables
We want only to remove the tables in order to preserve user privileges
```sql
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'bremen_calling';
```
outputs complete drop statements
```sql
SET FOREIGN_KEY_CHECKS = 0;
-- Your semicolon separated list of DROP statements here
DROP TABLE IF EXISTS `notification`;
DROP TABLE IF EXISTS `role`;
DROP TABLE IF EXISTS `ship`;
DROP TABLE IF EXISTS `participant`;
DROP TABLE IF EXISTS `times`;
DROP TABLE IF EXISTS `role_securable_map`;
DROP TABLE IF EXISTS `user_role_map`;
DROP TABLE IF EXISTS `user`;
DROP TABLE IF EXISTS `securable`;
DROP TABLE IF EXISTS `shipcall_participant_map`;
DROP TABLE IF EXISTS `berth`;
DROP TABLE IF EXISTS `shipcall`;
SET FOREIGN_KEY_CHECKS = 1;
```

View File

@ -0,0 +1,27 @@
{
"id": "a3b2b291-6ec7-4af8-9ba6-57448547f71b",
"name": "Remote BreCal EMSWE",
"values": [
{
"key": "PATH",
"value": "brecal.bsmd-emswe.eu/",
"type": "default",
"enabled": true
},
{
"key": "LOGON_TOKEN",
"value": "",
"type": "any",
"enabled": true
},
{
"key": "SCHEMA",
"value": "https://",
"type": "default",
"enabled": true
}
],
"_postman_variable_scope": "environment",
"_postman_exported_at": "2023-06-27T09:33:59.460Z",
"_postman_exported_using": "Postman/10.15.4"
}

32
misc/add_user.py Normal file
View File

@ -0,0 +1,32 @@
import mysql.connector
import os
import json
import bcrypt
config_path = '../src/server/BreCal/connection_data.json'
print (os.getcwd())
if not os.path.exists(config_path):
print ('cannot find ' + config_path)
exit(1)
f = open(config_path);
connection_data = json.load(f)
mydb = mysql.connector.connect(host=connection_data["host"], user=connection_data["user"],
password = connection_data["password"], database=connection_data["database"])
print(mydb)
# insert a new user
participant_id = 1
first_name = "Londo"
last_name = "Mollari"
user_name = "Londo"
user_email = "l.mollari@centauri.gov"
user_phone = "+01 555 324 2313"
password = "Hallowach"
password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8')
query = "INSERT INTO user (participant_id, first_name, last_name, user_name, user_email, user_phone, password_hash) VALUES (" + str(participant_id) + ",\"" + first_name + "\",\"" + last_name + "\",\"" + user_name + "\",\"" + user_email + "\",\"" + user_phone + "\",\"" + password_hash + "\")"
with mydb.cursor() as cursor:
cursor.execute(query)
mydb.commit()

BIN
misc/brecal.snk Normal file

Binary file not shown.

264
misc/create_schema.sql Normal file
View File

@ -0,0 +1,264 @@
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server Version: 8.0.34-0ubuntu0.22.04.1 - (Ubuntu)
-- Server Betriebssystem: Linux
-- HeidiSQL Version: 10.2.0.5599
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Exportiere Struktur von Tabelle bremen_calling.berth
CREATE TABLE IF NOT EXISTS `berth` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL COMMENT 'Descriptive name',
`participant_id` int unsigned DEFAULT NULL COMMENT 'If berth belongs to a participant, reference it here',
`lock` bit(1) DEFAULT NULL COMMENT 'The lock must be used',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) DEFAULT b'0',
PRIMARY KEY (`id`),
KEY `FK_BERTH_PART` (`participant_id`),
CONSTRAINT `FK_BERTH_PART` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Berth of ship for a ship call';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.notification
CREATE TABLE IF NOT EXISTS `notification` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`times_id` int unsigned NOT NULL COMMENT 'times record that caused the notification',
`participant_id` int unsigned NOT NULL COMMENT 'participant ref',
`acknowledged` bit(1) DEFAULT b'0' COMMENT 'true if UI acknowledged',
`level` tinyint DEFAULT NULL COMMENT 'severity of the notification',
`type` tinyint DEFAULT NULL COMMENT 'Email/UI/Other',
`message` varchar(256) DEFAULT NULL COMMENT 'individual message',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_NOT_TIMES` (`times_id`),
KEY `FK_NOT_PART` (`participant_id`),
CONSTRAINT `FK_NOT_PART` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`),
CONSTRAINT `FK_NOT_TIMES` FOREIGN KEY (`times_id`) REFERENCES `times` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='An entry corresponds to an alarm given by a violated rule during times update';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.participant
CREATE TABLE IF NOT EXISTS `participant` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`street` varchar(128) DEFAULT NULL,
`postal_code` varchar(5) DEFAULT NULL,
`city` varchar(64) DEFAULT NULL,
`type` int DEFAULT NULL,
`flags` int unsigned DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) DEFAULT b'0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='An organization taking part';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.role
CREATE TABLE IF NOT EXISTS `role` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '0' COMMENT 'unique role name',
`description` varchar(255) DEFAULT '0' COMMENT 'role description',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='logical group of securables for one or more user';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.role_securable_map
CREATE TABLE IF NOT EXISTS `role_securable_map` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`role_id` int unsigned NOT NULL,
`securable_id` int unsigned NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_ROLE_SECURABLE` (`role_id`),
KEY `FK_SECURABLE_ROLE` (`securable_id`),
CONSTRAINT `FK_ROLE_SECURABLE` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
CONSTRAINT `FK_SECURABLE_ROLE` FOREIGN KEY (`securable_id`) REFERENCES `securable` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Assigns securables to roles';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.securable
CREATE TABLE IF NOT EXISTS `securable` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Actual permission on a single(!) feature or operation';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.ship
CREATE TABLE IF NOT EXISTS `ship` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT NULL,
`imo` int DEFAULT NULL,
`callsign` varchar(8) DEFAULT NULL,
`participant_id` int unsigned DEFAULT NULL,
`length` float DEFAULT NULL,
`width` float DEFAULT NULL,
`is_tug` bit(1) DEFAULT b'0',
`bollard_pull` int DEFAULT NULL,
`eni` int DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`deleted` bit(1) DEFAULT b'0',
PRIMARY KEY (`id`),
KEY `FK_SHIP_PARTICIPANT` (`participant_id`),
CONSTRAINT `FK_SHIP_PARTICIPANT` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.shipcall
CREATE TABLE IF NOT EXISTS `shipcall` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`ship_id` int unsigned DEFAULT NULL,
`type` tinyint DEFAULT NULL,
`eta` datetime DEFAULT NULL,
`voyage` varchar(16) DEFAULT NULL,
`etd` datetime DEFAULT NULL,
`arrival_berth_id` int unsigned DEFAULT NULL,
`departure_berth_id` int unsigned DEFAULT NULL,
`tug_required` bit(1) DEFAULT NULL,
`pilot_required` bit(1) DEFAULT NULL,
`flags` int unsigned DEFAULT '0',
`pier_side` bit(1) DEFAULT NULL,
`bunkering` bit(1) DEFAULT NULL,
`replenishing_terminal` bit(1) DEFAULT NULL,
`replenishing_lock` bit(1) DEFAULT NULL,
`draft` float DEFAULT NULL,
`tidal_window_from` datetime DEFAULT NULL,
`tidal_window_to` datetime DEFAULT NULL,
`rain_sensitive_cargo` bit(1) DEFAULT b'0',
`recommended_tugs` int DEFAULT '0',
`anchored` bit(1) DEFAULT NULL,
`moored_lock` bit(1) DEFAULT NULL,
`canceled` bit(1) DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_SHIPCALL_SHIP` (`ship_id`),
KEY `FK_SHIPCALL_BERTH_ARRIVAL` (`arrival_berth_id`),
KEY `FK_SHIPCALL_BERTH_DEPARTURE` (`departure_berth_id`),
CONSTRAINT `FK_SHIPCALL_BERTH_ARRIVAL` FOREIGN KEY (`arrival_berth_id`) REFERENCES `berth` (`id`),
CONSTRAINT `FK_SHIPCALL_BERTH_DEPARTURE` FOREIGN KEY (`departure_berth_id`) REFERENCES `berth` (`id`),
CONSTRAINT `FK_SHIPCALL_SHIP` FOREIGN KEY (`ship_id`) REFERENCES `ship` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Incoming, outgoing or moving to another berth';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.shipcall_participant_map
CREATE TABLE IF NOT EXISTS `shipcall_participant_map` (
`id` int NOT NULL AUTO_INCREMENT,
`shipcall_id` int unsigned DEFAULT NULL,
`participant_id` int unsigned DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_MAP_PARTICIPANT_SHIPCALL` (`shipcall_id`),
KEY `FK_MAP_SHIPCALL_PARTICIPANT` (`participant_id`),
CONSTRAINT `FK_MAP_PARTICIPANT_SHIPCALL` FOREIGN KEY (`shipcall_id`) REFERENCES `shipcall` (`id`),
CONSTRAINT `FK_MAP_SHIPCALL_PARTICIPANT` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Associates a participant with a shipcall';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.shipcall_tug_map
CREATE TABLE IF NOT EXISTS `shipcall_tug_map` (
`id` int NOT NULL AUTO_INCREMENT,
`shipcall_id` int unsigned NOT NULL COMMENT 'Ref to ship call',
`ship_id` int unsigned NOT NULL COMMENT 'Ref to ship (that is a tug)',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_SCT_SHIP` (`ship_id`),
KEY `FK_SCT_SHIPCALL` (`shipcall_id`),
CONSTRAINT `FK_SCT_SHIP` FOREIGN KEY (`ship_id`) REFERENCES `ship` (`id`),
CONSTRAINT `FK_SCT_SHIPCALL` FOREIGN KEY (`shipcall_id`) REFERENCES `shipcall` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Mapping table that assigns tugs to a ship call';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.times
CREATE TABLE IF NOT EXISTS `times` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`eta_berth` datetime DEFAULT NULL,
`eta_berth_fixed` bit(1) DEFAULT NULL,
`etd_berth` datetime DEFAULT NULL,
`etd_berth_fixed` bit(1) DEFAULT NULL,
`lock_time` datetime DEFAULT NULL,
`lock_time_fixed` bit(1) DEFAULT NULL,
`zone_entry` datetime DEFAULT NULL,
`zone_entry_fixed` bit(1) DEFAULT NULL,
`operations_start` datetime DEFAULT NULL,
`operations_end` datetime DEFAULT NULL,
`remarks` varchar(512) DEFAULT NULL,
`shipcall_id` int unsigned NOT NULL,
`participant_id` int unsigned NOT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_TIME_SHIPCALL` (`shipcall_id`),
KEY `FK_TIME_PART` (`participant_id`),
CONSTRAINT `FK_TIME_PART` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='the planned time for the participants work';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.user
CREATE TABLE IF NOT EXISTS `user` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`participant_id` int unsigned DEFAULT NULL,
`first_name` varchar(45) DEFAULT NULL,
`last_name` varchar(45) DEFAULT NULL,
`user_name` varchar(45) DEFAULT NULL,
`user_email` varchar(128) DEFAULT NULL,
`user_phone` varchar(128) DEFAULT NULL,
`password_hash` varchar(128) DEFAULT NULL,
`api_key` varchar(256) DEFAULT NULL,
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_USER_PART` (`participant_id`),
CONSTRAINT `FK_USER_PART` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='member of a participant';
-- Daten Export vom Benutzer nicht ausgewählt
-- Exportiere Struktur von Tabelle bremen_calling.user_role_map
CREATE TABLE IF NOT EXISTS `user_role_map` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`user_id` int unsigned NOT NULL DEFAULT '0',
`role_id` int unsigned NOT NULL DEFAULT '0',
`created` datetime DEFAULT CURRENT_TIMESTAMP,
`modified` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_USER_ROLE` (`user_id`),
KEY `FK_ROLE_USER` (`role_id`),
CONSTRAINT `FK_ROLE_USER` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
CONSTRAINT `FK_USER_ROLE` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Assigns a user to a role';
-- Daten Export vom Benutzer nicht ausgewählt
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

136
misc/sample_data.sql Normal file
View File

@ -0,0 +1,136 @@
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server Version: 8.0.34-0ubuntu0.22.04.1 - (Ubuntu)
-- Server Betriebssystem: Linux
-- HeidiSQL Version: 10.2.0.5599
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Exportiere Daten aus Tabelle bremen_calling.berth: ~3 rows (ungefähr)
/*!40000 ALTER TABLE `berth` DISABLE KEYS */;
INSERT INTO `berth` (`id`, `name`, `participant_id`, `lock`, `created`, `modified`, `deleted`) VALUES
(1, 'Roland Mühle', NULL, NULL, '2023-06-26 14:01:40', NULL, b'0'),
(2, 'Stahlwerk', NULL, NULL, '2023-06-26 14:01:40', NULL, b'0'),
(3, 'Kellogs', NULL, NULL, '2023-06-26 14:01:40', NULL, b'0');
/*!40000 ALTER TABLE `berth` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.notification: ~0 rows (ungefähr)
/*!40000 ALTER TABLE `notification` DISABLE KEYS */;
/*!40000 ALTER TABLE `notification` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.participant: ~11 rows (ungefähr)
/*!40000 ALTER TABLE `participant` DISABLE KEYS */;
INSERT INTO `participant` (`id`, `name`, `street`, `postal_code`, `city`, `type`, `flags`, `created`, `modified`, `deleted`) VALUES
(1, 'Schick Informatik', 'Gottlieb-Daimler-Str. 8', '73614', 'Schorndorf', 1, 42, '2023-04-17 07:18:19', '2023-08-07 11:35:37', b'0'),
(2, 'Lotsenbrüderschaft Weser 1', '', '', '', 4, 0, '2023-08-10 07:07:41', NULL, b'0'),
(3, 'Bremer Schiffsmeldedienst', 'Hafenkopf II / Überseetor 20', '28217', 'Bremen', 1, 0, '2023-08-10 07:11:10', NULL, b'0'),
(4, 'BLG Cargo Logistics GmbH', '', '', '', 2, 0, '2023-08-10 07:14:40', NULL, b'0'),
(5, 'Schiffsmakler-Verband für Küsten und Seeschiffsbefrachter e.V.', '', '', '', 8, 0, '2023-08-10 07:15:56', NULL, b'0'),
(6, 'RMS Rhenus Maritime Services GmbH', '', '', '', 8, 0, '2023-08-10 07:19:29', NULL, b'0'),
(7, 'J.MÜLLER Weser GmbH & Co. KG', '', '', '', 10, 0, '2023-08-10 07:21:43', '2023-08-10 08:47:59', b'0'),
(8, 'Schiffahrtskontor Detra GmbH & Co.KG', '', '', '', 8, 0, '2023-08-10 07:23:04', NULL, b'0'),
(9, 'Boluda Deutschland GmbH', '', '', '', 64, 0, '2023-08-10 07:24:18', NULL, b'0'),
(10, 'Weserport GmbH', '', '', '', 10, 0, '2023-08-10 07:26:42', '2023-08-10 08:48:19', b'0'),
(11, 'Port Authority Bremen', '', '', '', 32, 0, '2023-08-10 07:28:11', NULL, b'0');
/*!40000 ALTER TABLE `participant` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.role: ~2 rows (ungefähr)
/*!40000 ALTER TABLE `role` DISABLE KEYS */;
INSERT INTO `role` (`id`, `name`, `description`, `created`, `modified`) VALUES
(1, 'My first role', 'A very good description', '2023-04-17 07:31:57', NULL),
(2, 'Another role', 'This role is very nice as well', '2023-04-17 07:32:12', NULL);
/*!40000 ALTER TABLE `role` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.role_securable_map: ~0 rows (ungefähr)
/*!40000 ALTER TABLE `role_securable_map` DISABLE KEYS */;
/*!40000 ALTER TABLE `role_securable_map` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.securable: ~2 rows (ungefähr)
/*!40000 ALTER TABLE `securable` DISABLE KEYS */;
INSERT INTO `securable` (`id`, `name`, `created`, `modified`) VALUES
(1, 'First secure thing', '2023-04-17 07:38:12', NULL),
(2, 'Another secure thing', '2023-04-17 07:38:22', NULL);
/*!40000 ALTER TABLE `securable` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.ship: ~2 rows (ungefähr)
/*!40000 ALTER TABLE `ship` DISABLE KEYS */;
INSERT INTO `ship` (`id`, `name`, `imo`, `callsign`, `participant_id`, `length`, `width`, `is_tug`, `bollard_pull`, `eni`, `created`, `modified`, `deleted`) VALUES
(1, 'Dicke Berta', 1234567, 'DEBE', 1, 100, 20, b'0', NULL, NULL, '2023-06-27 10:43:02', NULL, b'0'),
(2, 'Maersk Neston', 9632167, '9V3532', 1, 210.07, 30.2, b'0', NULL, NULL, '2023-07-27 12:34:13', NULL, b'0');
/*!40000 ALTER TABLE `ship` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.shipcall: ~8 rows (ungefähr)
/*!40000 ALTER TABLE `shipcall` DISABLE KEYS */;
INSERT INTO `shipcall` (`id`, `ship_id`, `type`, `eta`, `voyage`, `etd`, `arrival_berth_id`, `departure_berth_id`, `tug_required`, `pilot_required`, `flags`, `pier_side`, `bunkering`, `replenishing_terminal`, `replenishing_lock`, `draft`, `tidal_window_from`, `tidal_window_to`, `rain_sensitive_cargo`, `recommended_tugs`, `anchored`, `moored_lock`, `canceled`, `created`, `modified`) VALUES
(3, 1, 1, '2023-08-13 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 3, NULL, NULL, NULL, '2023-06-27 11:03:28', '2023-08-07 15:19:56'),
(4, 2, 1, '2023-08-14 10:43:02', '43', NULL, NULL, NULL, NULL, NULL, 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, b'0', 0, NULL, NULL, NULL, '2023-07-27 12:36:49', '2023-08-07 15:19:56'),
(5, 1, 1, '2023-07-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 2, NULL, NULL, NULL, '2023-08-11 15:11:50', NULL),
(6, 1, 1, '2023-07-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 2, NULL, NULL, NULL, '2023-08-11 15:11:53', NULL),
(7, 1, 1, '2023-07-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 2, NULL, NULL, NULL, '2023-08-13 12:12:34', NULL),
(8, 1, 1, '2023-07-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 2, NULL, NULL, NULL, '2023-08-13 12:14:52', NULL),
(9, 1, 1, '2023-07-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 2, NULL, NULL, NULL, '2023-08-13 12:17:09', NULL),
(10, 1, 1, '2023-08-23 07:18:19', '43B', NULL, NULL, NULL, b'0', b'1', 0, b'0', b'1', NULL, NULL, NULL, NULL, NULL, b'0', 3, NULL, NULL, NULL, '2023-08-14 07:55:48', '2023-08-14 07:56:52');
/*!40000 ALTER TABLE `shipcall` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.shipcall_participant_map: ~6 rows (ungefähr)
/*!40000 ALTER TABLE `shipcall_participant_map` DISABLE KEYS */;
INSERT INTO `shipcall_participant_map` (`id`, `shipcall_id`, `participant_id`, `created`, `modified`) VALUES
(1, 3, 2, '2023-08-11 15:01:23', NULL),
(2, 3, 4, '2023-08-11 15:01:29', NULL),
(3, 9, 2, '2023-08-13 12:17:17', NULL),
(4, 9, 4, '2023-08-13 12:17:18', NULL),
(24, 10, 3, '2023-08-14 08:48:30', NULL),
(26, 10, 9, '2023-08-14 09:03:29', NULL);
/*!40000 ALTER TABLE `shipcall_participant_map` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.shipcall_tug_map: ~0 rows (ungefähr)
/*!40000 ALTER TABLE `shipcall_tug_map` DISABLE KEYS */;
/*!40000 ALTER TABLE `shipcall_tug_map` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.times: ~0 rows (ungefähr)
/*!40000 ALTER TABLE `times` DISABLE KEYS */;
INSERT INTO `times` (`id`, `eta_berth`, `eta_berth_fixed`, `etd_berth`, `etd_berth_fixed`, `lock_time`, `lock_time_fixed`, `zone_entry`, `zone_entry_fixed`, `operations_start`, `operations_end`, `remarks`, `shipcall_id`, `participant_id`, `created`, `modified`) VALUES
(1, '2023-05-18 07:18:19', NULL, '2023-05-18 09:18:19', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3, 1, '2023-06-27 11:05:01', '2023-06-27 11:05:30');
/*!40000 ALTER TABLE `times` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.user: ~21 rows (ungefähr)
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` (`id`, `participant_id`, `first_name`, `last_name`, `user_name`, `user_email`, `user_phone`, `password_hash`, `api_key`, `created`, `modified`) VALUES
(1, 1, 'Daniel', 'Schick', 'dani', NULL, NULL, '$2b$12$qfjw4b3XvGuu0t6HR8OYGOzF5b8gmC6PyIIBNbIXMXEayJunEEKmi', '0815', '2023-04-17 07:15:41', '2023-08-11 11:11:34'),
(2, 1, 'Londo', 'Mollari', 'Londo', 'l.mollari@centauri.gov', '+01 555 324 2313', '$2b$12$VwmwvO2dxlOixWc1HjX3j.753SDJTMR.o7av/bVGTM2tLW2jQT0yy', NULL, '2023-06-27 08:34:55', NULL),
(3, 2, 'Maik', 'Baudeck', 'maikb', NULL, NULL, '$2b$12$4SxGRlinOrpEVvqDZcE.wOusMZYsepdc6vj1vDpNhbPtApxU8VGPi', '', '2023-08-10 07:09:35', '2023-08-11 11:11:55'),
(4, 3, 'Christin', 'Hollmann', 'christinh', NULL, NULL, '$2b$12$ul0QJmcuUhktDYDjcyEpx.6yY1ieLdaCxZ6a3SFSuTq94IqK4Y/re', '', '2023-08-10 07:12:05', '2023-08-11 11:10:33'),
(5, 3, 'Bastian', 'Güttner', 'bastiang', NULL, NULL, '$2b$12$0oCX3c2WyMykmxMoLqmpNubke713xhYlEEQgnxBV6Fj/TaUn.3/U6', '', '2023-08-10 07:12:26', '2023-08-11 11:11:13'),
(6, 3, 'Benjamin', 'Wiese', 'benjaminw', NULL, NULL, '$2b$12$RRj32KdLIf3D7z7cVWFqa.yZM5.ODOS0HqU3rdCuFrJS8HJ/rtqwy', '', '2023-08-10 07:13:01', '2023-08-11 11:11:16'),
(7, 1, 'Sladjan', 'Veselinovic', 'sladjanv', NULL, NULL, '$2b$12$4DctoCbZwxTvE39lXNRzneQ2kb/lXlJ5wEZ1CGbbw.rGM3nuAYjpa', '', '2023-08-10 07:13:39', '2023-08-11 11:11:45'),
(8, 1, 'Kersten', 'Gevers', 'kersteng', NULL, NULL, '$2b$12$zKX8iLPnXRmp5wD1Yp8P7e..U9R0A4ytbiMjd.l.IGkMzahcHPNWq', '', '2023-08-10 07:13:59', '2023-08-11 11:11:49'),
(9, 4, 'Dirk', 'Brunnert', 'dirkb', NULL, NULL, '$2b$12$HTeq/Fdfse6oElk7DLsQae5dtvWJloee.VtBH.THsj2kdcxxBkCDW', '', '2023-08-10 07:15:01', '2023-08-11 11:12:01'),
(10, 5, 'Thorsten', 'Fischer', 'thorstenf', NULL, NULL, '$2b$12$NHEpTNHuKU4ruPRIfd9yc.yv5faHGemFfRI3TISniqM7QNqHiyZpK', '', '2023-08-10 07:16:20', '2023-08-11 11:12:07'),
(11, 6, 'Lisa', 'Friedhoff', 'lisaf', NULL, NULL, '$2b$12$DJKJHGrQwfY9pwzgFfPds.DHGsygHyV3KDs38Hq4AUHPPs3jBPH3y', '', '2023-08-10 07:19:52', '2023-08-11 11:12:12'),
(12, 6, 'Dario', 'Fritschi', 'dariof', NULL, NULL, '$2b$12$MwCVTMQkN6zCAzCsE572Ye.M0nRDQNld4AgorLVyWq.DcQEmAy5lu', '', '2023-08-10 07:20:11', '2023-08-11 11:12:15'),
(13, 7, 'Hergen', 'Hanke', 'hergenh', NULL, NULL, '$2b$12$MKb6BDRrTbNd0qg5BdAS.upzlqxcWOgU/VEafJKSuzE9JLIWCimq6', '', '2023-08-10 07:22:09', '2023-08-11 11:12:24'),
(14, 8, 'Hardy', 'Paasch', 'hardyp', NULL, NULL, '$2b$12$l1lE/UqnYnOvci.N4j3zBOz6HC0z87ovnO0n6BIZYO7VN8gj.qGey', '', '2023-08-10 07:23:25', '2023-08-11 11:12:28'),
(15, 8, 'Marc', 'Pagel', 'marcp', NULL, NULL, '$2b$12$UCVJKzqX92Z8xZJ4kK0BRuFXMRdqcaXaGmBrqnYWARdKlPvZvLUZq', '', '2023-08-10 07:23:41', '2023-08-11 11:12:30'),
(16, 9, 'Andreas', 'Peukert', 'andreasp', NULL, NULL, '$2b$12$jNmciJAVR6p0IflvAthmk.j0SoOBvFHwDiEDKUHfwJq7baRsKg/LG', '', '2023-08-10 07:24:37', '2023-08-11 11:12:45'),
(17, 8, 'Christina', 'Rachiele', 'christinar', NULL, NULL, '$2b$12$BCsVgPRuIWPuuor07lprF.klQxvF901O3AXUhRrBJoEvYIjNQ.HKS', '', '2023-08-10 07:25:05', '2023-08-11 11:12:33'),
(18, 9, 'Sonia', 'Rekawek', 'soniar', NULL, NULL, '$2b$12$uHCkH6gu13yqllXBibLFIOWOpvctMC7NmojtXqDd6xsLq7bmvNOMu', '', '2023-08-10 07:25:27', '2023-08-11 11:12:48'),
(19, 6, 'Frank', 'Roelfs', 'frankr', NULL, NULL, '$2b$12$cEQAhUe9VJV6uTkfOY6/R.oAVfmFZQ4vS5G6BqoNEyaVHtFRDtB56', '', '2023-08-10 07:26:04', '2023-08-11 11:12:19'),
(20, 10, 'Vera', 'Schliedermann', 'veras', NULL, NULL, '$2b$12$FKcitW6W1HPwd.cdkZLGLeTFuzjsEIrbiKInysAKN.RibZ4gVLZHi', '', '2023-08-10 07:27:01', '2023-08-11 11:12:54'),
(21, 8, 'Michael', 'Strudthoff', 'michaels', NULL, NULL, '$2b$12$doTiywWpkso1UWB5eiAW1eoACP6rN4UDVt7qFFdRFvhhWUXikCmS2', '', '2023-08-10 07:27:27', '2023-08-11 11:12:37'),
(22, 4, 'Volker', 'Viohl', 'volkerv', NULL, NULL, '$2b$12$.YavQbWNE4eJDQA.ZNSKROYvMPWifBXyMX0IL0H2z50M720fpfTJW', '', '2023-08-10 07:27:50', '2023-08-11 11:12:04'),
(23, 11, 'Frauke', 'Zabel', 'fraukez', NULL, NULL, '$2b$12$rawQg6Cjl1yECGm9DOG8degdWdD.nZjEgGp8eXO98nh11QV1sEEEO', '', '2023-08-10 07:28:33', '2023-08-11 11:12:58'),
(24, 8, 'Jan', 'Zierow', 'janz', NULL, NULL, '$2b$12$CbnjUT42cf0mkIAqAURg3OksP9G3brmsE2GQTECTZ4.cVuhPn5D2G', '', '2023-08-10 07:28:55', '2023-08-11 11:12:39');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
-- Exportiere Daten aus Tabelle bremen_calling.user_role_map: ~0 rows (ungefähr)
/*!40000 ALTER TABLE `user_role_map` DISABLE KEYS */;
/*!40000 ALTER TABLE `user_role_map` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@ -0,0 +1,135 @@
[*.cs]
# CS8073: The result of the expression is always the same since a value of this type is never equal to 'null'
dotnet_diagnostic.CS8073.severity = none
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_throw_expression = true:suggestion
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_prefer_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_indent_labels = one_less_than_current
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
csharp_space_around_binary_operators = before_and_after
csharp_style_prefer_tuple_swap = true:suggestion
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
csharp_style_conditional_delegate_call = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_extended_property_pattern = true:suggestion
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
csharp_style_var_elsewhere = false:silent
# IDE1006: Naming Styles
dotnet_diagnostic.IDE1006.severity = none
[*.{cs,vb}]
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_readonly_field = true:suggestion
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
dotnet_code_quality_unused_parameters = all:suggestion
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_event = false:silent

View File

@ -0,0 +1,52 @@
<Window x:Class="BreCalClient.AboutDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BreCalClient"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p = "clr-namespace:BreCalClient.Resources"
mc:Ignorable="d"
Title="Help" Height="270" Width="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="10" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="Projektleitung" HorizontalContentAlignment="Right"/>
<Label Grid.Column="0" Grid.Row="1" Content="Softwareentwicklung" HorizontalContentAlignment="Right"/>
<TextBlock Grid.Column="1" Grid.Row="0" VerticalAlignment="Center">
<Hyperlink NavigateUri="https://www.bsmd.de" RequestNavigate="Hyperlink_RequestNavigate">
Bremer Schiffsmeldedienst
</Hyperlink>
</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="1" VerticalAlignment="Center">
<Hyperlink NavigateUri="http://www.textbausteine.net/" RequestNavigate="Hyperlink_RequestNavigate">
Informatikbüro Daniel Schick
</Hyperlink>
</TextBlock>
<Label FontWeight="DemiBold" Grid.Row="3" Grid.Column="0" Content="{x:Static p:Resources.textChangePassword}" HorizontalContentAlignment="Right"/>
<xctk:WatermarkPasswordBox Watermark="{x:Static p:Resources.textOldPassword}" Grid.Column="1" Grid.Row="3" Margin="2" x:Name="wpBoxOldPassword" TextChanged="wpBoxOldPassword_TextChanged"/>
<xctk:WatermarkPasswordBox Watermark="{x:Static p:Resources.textNewPassword}" Grid.Column="1" Grid.Row="4" Margin="2" x:Name="wpBoxNewPassword" TextChanged="wpBoxOldPassword_TextChanged"/>
<xctk:WatermarkPasswordBox Watermark="{x:Static p:Resources.textRepeatNewPassword}" Grid.Column="1" Grid.Row="5" Margin="2" x:Name="wpBoxNewPasswordRepeat" TextChanged="wpBoxOldPassword_TextChanged"/>
<Button x:Name="buttonChangePassword" Click="buttonChangePassword_Click" Grid.Column="1" Grid.Row="6" Margin="2" Content="{x:Static p:Resources.textChange}" Width="80" HorizontalAlignment="Left" IsEnabled="False" />
<Button x:Name="buttonClose" Click="buttonClose_Click" Content="{x:Static p:Resources.textClose}" Width="80" Margin="2" Grid.Column="1" Grid.Row="8" HorizontalAlignment="Right" />
</Grid>
</Window>

View File

@ -0,0 +1,64 @@
// Copyright (c) 2023 schick Informatik
// Description: Show about info and allow user detail editing
//
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for AboutDialog.xaml
/// </summary>
public partial class AboutDialog : Window
{
#region Construction
public AboutDialog()
{
InitializeComponent();
}
#endregion
#region events
public event Action<string, string>? ChangePasswordRequested;
#endregion
#region event handler
private void buttonClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void buttonChangePassword_Click(object sender, RoutedEventArgs e)
{
this.ChangePasswordRequested?.Invoke(this.wpBoxOldPassword.Password, this.wpBoxNewPassword.Password);
}
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
e.Handled = true;
}
private void wpBoxOldPassword_TextChanged(object sender, TextChangedEventArgs e)
{
this.buttonChangePassword.IsEnabled =
(this.wpBoxOldPassword.Password.Length > 0) &&
(this.wpBoxNewPassword.Password.Length > 0) &&
(this.wpBoxNewPasswordRepeat.Password.Length > 0) &&
this.wpBoxNewPassword.Password.Equals(this.wpBoxNewPasswordRepeat.Password) &&
(!this.wpBoxNewPassword.Password.Equals(this.wpBoxOldPassword.Password));
}
#endregion
}
}

17
src/BreCalClient/App.xaml Normal file
View File

@ -0,0 +1,17 @@
<Application x:Class="BreCalClient.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BreCalClient"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\StringResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -0,0 +1,13 @@
using BreCalClient.misc.Model;
using System.Windows;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static Participant Participant { get; set; } = new Participant();
}
}

View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@ -0,0 +1,23 @@
// Copyright (c) 2023 schick Informatik
// Description: Helper for combobox binding of bool to combobox
//
using System;
using System.Globalization;
using System.Windows.Data;
namespace BreCalClient
{
public class BoolToIndexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((bool) value == true) ? 0 : 1;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((int)value == 0);
}
}
}

View File

@ -0,0 +1,115 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<SignAssembly>True</SignAssembly>
<StartupObject>BreCalClient.App</StartupObject>
<AssemblyOriginatorKeyFile>E:\gitlager\git_brcal\misc\brecal.snk</AssemblyOriginatorKeyFile>
<AssemblyVersion>0.3.0.0</AssemblyVersion>
<FileVersion>0.3.0.0</FileVersion>
<Title>Bremen calling client</Title>
<Description>A Windows WPF client for the Bremen calling API.</Description>
<ApplicationIcon>containership.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\arrow_down_green.png" />
<None Remove="Resources\arrow_down_red.png" />
<None Remove="Resources\arrow_right_blue.png" />
<None Remove="Resources\arrow_up_green.png" />
<None Remove="Resources\arrow_up_red.png" />
<None Remove="Resources\clipboard.png" />
<None Remove="Resources\clock.png" />
<None Remove="Resources\containership.ico" />
<None Remove="Resources\containership.png" />
<None Remove="Resources\emergency_stop_button.png" />
<None Remove="Resources\logo_bremen_calling.png" />
<None Remove="Resources\ship2.png" />
<None Remove="Resources\trafficlight_green.png" />
<None Remove="Resources\trafficlight_off.png" />
<None Remove="Resources\trafficlight_on.png" />
<None Remove="Resources\trafficlight_red.png" />
<None Remove="Resources\trafficlight_red_yellow.png" />
<None Remove="Resources\trafficlight_yellow.png" />
<None Remove="Resources\umbrella_closed.png" />
<None Remove="Resources\umbrella_open.png" />
<None Remove="Resources\worker2.png" />
</ItemGroup>
<ItemGroup>
<Page Remove="Resources\StringResources.xaml" />
<Page Remove="StringResources.de.xaml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\misc\BreCalApi.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>BreCalApi.yaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Include="containership.ico" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\misc\BreCalApi.yaml" Link="BreCalApi.yaml">
<Generator>OpenApiCodeGenerator</Generator>
<LastGenOutput>BreCalApi.cs</LastGenOutput>
</None>
<Resource Include="Resources\arrow_down_green.png" />
<Resource Include="Resources\arrow_down_red.png" />
<Resource Include="Resources\arrow_right_blue.png" />
<Resource Include="Resources\arrow_up_green.png" />
<Resource Include="Resources\arrow_up_red.png" />
<Resource Include="Resources\clipboard.png" />
<Resource Include="Resources\clock.png" />
<Resource Include="Resources\containership.ico" />
<Resource Include="Resources\containership.png" />
<Resource Include="Resources\emergency_stop_button.png" />
<Resource Include="Resources\logo_bremen_calling.png" />
<Resource Include="Resources\ship2.png" />
<Resource Include="Resources\StringResources.de.xaml">
<Generator>MSBuild:Compile</Generator>
</Resource>
<Resource Include="Resources\StringResources.xaml" />
<Resource Include="Resources\trafficlight_green.png" />
<Resource Include="Resources\trafficlight_off.png" />
<Resource Include="Resources\trafficlight_on.png" />
<Resource Include="Resources\trafficlight_red.png" />
<Resource Include="Resources\trafficlight_red_yellow.png" />
<Resource Include="Resources\trafficlight_yellow.png" />
<Resource Include="Resources\umbrella_closed.png" />
<Resource Include="Resources\umbrella_open.png" />
<Resource Include="Resources\worker2.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.0" />
<PackageReference Include="JsonSubTypes" Version="2.0.1" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Polly" Version="7.2.3" />
<PackageReference Include="RestSharp" Version="108.0.2" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -0,0 +1,16 @@
extensions: designer.cs generated.cs
extensions: .cs .cpp .h
// Copyright (c) 2023 schick Informatik
// Description:
//
extensions: .aspx .ascx
<%--
Copyright (c) 2023 schick Informatik
--%>
extensions: .vb
'Sample license text.
extensions: .xml .config .xsd
<!--
Sample license text.
-->

View File

@ -0,0 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33627.172
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BreCalClient", "BreCalClient.csproj", "{FA9E0A87-FBFB-4F2B-B5FA-46DE2E5E4BCB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EE0DC107-4A84-442F-89B2-2FF2557F761A}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FA9E0A87-FBFB-4F2B-B5FA-46DE2E5E4BCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA9E0A87-FBFB-4F2B-B5FA-46DE2E5E4BCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA9E0A87-FBFB-4F2B-B5FA-46DE2E5E4BCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA9E0A87-FBFB-4F2B-B5FA-46DE2E5E4BCB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CBF797A4-0CAF-4F01-B0D5-708702165337}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,122 @@
<Window x:Class="BreCalClient.EditShipcallControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BreCalClient"
xmlns:p = "clr-namespace:BreCalClient.Resources"
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="{x:Static p:Resources.textEditShipcall}" Height="466" Width="800" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
<Window.Resources>
<local:BoolToIndexConverter x:Key="boolToIndexConverter" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.15*"/>
<ColumnDefinition Width=".35*" />
<ColumnDefinition Width="0.15*"/>
<ColumnDefinition Width=".35*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Label Content="{x:Static p:Resources.textShip}" Grid.Column="0" Grid.Row="0" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textType}" Grid.Column="0" Grid.Row="1" HorizontalContentAlignment="Right" />
<Label Content="ETA" Grid.Column="0" Grid.Row="2" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textVoyage}" Grid.Column="0" Grid.Row="3" HorizontalContentAlignment="Right"/>
<Label Content="ETD" Grid.Column="0" Grid.Row="4" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textArrivalTerminal}" Grid.Column="0" Grid.Row="5" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textDepartureTerminal}" Grid.Column="0" Grid.Row="6" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textTugRequired}" Grid.Column="1" Grid.Row="7" />
<Label Content="{x:Static p:Resources.textPilotRequired}" Grid.Column="1" Grid.Row="8" />
<Label Content="{x:Static p:Resources.textPierside}" Grid.Column="0" Grid.Row="9" HorizontalContentAlignment="Right" />
<Label Content="{x:Static p:Resources.textBunkering}" Grid.Column="1" Grid.Row="10" />
<Label Content="{x:Static p:Resources.textReplenishingTerminal}" Grid.Column="1" Grid.Row="11" />
<Label Content="{x:Static p:Resources.textReplenishingLock}" Grid.Column="1" Grid.Row="12" />
<Label Content="{x:Static p:Resources.textDraft}" Grid.Column="0" Grid.Row="13" HorizontalContentAlignment="Right" />
<ComboBox x:Name="comboBoxShip" Margin="2" Grid.Column="1" Grid.Row="0" SelectionChanged="comboBoxShip_SelectionChanged" SelectedValuePath="Id">
<ComboBox.ItemTemplate>
<DataTemplate>
<!--Border-->
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name" />
<Binding Path="Imo" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<!--/Border-->
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="comboBoxCategories" Grid.Column="1" Margin="2" Grid.Row="1" SelectedValuePath="Key"/>
<xctk:DateTimePicker x:Name="datePickerETA" Grid.Column="1" Grid.Row="2" Margin="2" />
<TextBox x:Name="textBoxVoyage" Grid.Column="1" Grid.Row="3" Margin="2" VerticalContentAlignment="Center" />
<xctk:DateTimePicker x:Name="datePickerETD" Grid.Column="1" Grid.Row="4" Margin="2" />
<ComboBox Name="comboBoxArrivalBerth" Grid.Column="1" Grid.Row="5" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" />
<ComboBox Name="comboBoxDepartureBerth" Grid.Column="1" Grid.Row="6" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id" />
<CheckBox x:Name="checkBoxTugRequired" Grid.Column="0" Grid.Row="7" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<CheckBox x:Name="checkBoxPilotRequired" Grid.Column="0" Grid.Row="8" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<ComboBox x:Name="comboBoxPierside" Grid.Column="1" Grid.Row="9" Margin="2" >
<ComboBoxItem Content="{x:Static p:Resources.textNotRotated}" />
<ComboBoxItem Content="{x:Static p:Resources.textRotated}" />
</ComboBox>
<CheckBox x:Name="checkBoxBunkering" Grid.Column="0" Grid.Row="10" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<CheckBox x:Name="checkBoxReplenishingTerminal" Grid.Column="0" Grid.Row="11" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<CheckBox x:Name="checkBoxReplenishingLock" Grid.Column="0" Grid.Row="12" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<xctk:DoubleUpDown x:Name="doubleUpDownDraft" Grid.Column="1" Grid.Row="13" Margin="2" FormatString="N2" Minimum="0" />
<Label Content="{x:Static p:Resources.textParticipants}" FontWeight="DemiBold" Grid.Column="3" Grid.Row="0" />
<Label Content="{x:Static p:Resources.textAgency}" Grid.Column="2" Grid.Row="1" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textMooring}" Grid.Column="2" Grid.Row="2" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textPilot}" Grid.Column="2" Grid.Row="3" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textTug}" Grid.Column="2" Grid.Row="4" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textTerminal}" Grid.Column="2" Grid.Row="5" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textTidalWindow}" FontWeight="DemiBold" Grid.Column="3" Grid.Row="6" />
<Label Content="{x:Static p:Resources.textFrom}" Grid.Column="2" Grid.Row="7" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textTo}" Grid.Column="2" Grid.Row="8" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textRainSensitiveCargo}" Grid.Column="3" Grid.Row="9" />
<Label Content="{x:Static p:Resources.textRecommendedTugs}" Grid.Column="2" Grid.Row="10" HorizontalContentAlignment="Right"/>
<Label Content="{x:Static p:Resources.textAnchored}" Grid.Column="3" Grid.Row="11" />
<Label Content="{x:Static p:Resources.textMooredLock}" Grid.Column="3" Grid.Row="12" />
<Label Content="{x:Static p:Resources.textCancelled}" Grid.Column="3" Grid.Row="13" />
<ComboBox Name="comboBoxAgency" Grid.Column="3" Grid.Row="1" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id"/>
<ComboBox Name="comboBoxMooring" Grid.Column="3" Grid.Row="2" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id"/>
<ComboBox Name="comboBoxPilot" Grid.Column="3" Grid.Row="3" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id"/>
<ComboBox Name="comboBoxTug" Grid.Column="3" Grid.Row="4" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id"/>
<ComboBox Name="comboBoxTerminal" Grid.Column="3" Grid.Row="5" Margin="2" DisplayMemberPath="Name" SelectedValuePath="Id"/>
<xctk:DateTimePicker Name="datePickerTidalWindowFrom" Grid.Column="3" Grid.Row="7" Margin="2" />
<xctk:DateTimePicker Name="datePickerTidalWindowTo" Grid.Column="3" Grid.Row="8" Margin="2" />
<CheckBox x:Name="checkBoxRainsensitiveCargo" Grid.Column="2" Grid.Row="9" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<xctk:IntegerUpDown x:Name="integerUpDownRecommendedTugs" Grid.Column="3" Grid.Row="10" Minimum="0" Margin="2" />
<CheckBox x:Name="checkBoxAnchored" Grid.Column="2" Grid.Row="11" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<CheckBox x:Name="checkBoxMooredLock" Grid.Column="2" Grid.Row="12" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<CheckBox x:Name="checkBoxCanceled" Grid.Column="2" Grid.Row="13" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0" />
<StackPanel Grid.Row="14" Grid.Column="3" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" IsEnabled="False" />
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,195 @@
// Copyright (c) 2023 schick Informatik
// Description: Windows dialog to create / edit ship calls
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for EditShipcallControl.xaml
/// </summary>
public partial class EditShipcallControl : Window
{
public EditShipcallControl()
{
InitializeComponent();
}
#region Properties
public Shipcall Shipcall { get; set; } = new ();
public List<Participant> Participants { get; set; } = new();
public List<Berth> Berths { get; set; } = new();
public List<Ship> Ships { get; set; } = new();
public Ship? SelectedShip {
get
{
return this.comboBoxShip.SelectedItem as Ship;
}
}
#endregion
#region Event handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
List<Participant> aList = new();
List<Participant> mList = new();
List<Participant> pList = new();
List<Participant> tList = new();
List<Participant> terList = new();
foreach(Participant p in Participants)
{
if (p.IsFlagSet(Extensions.ParticipantType.AGENCY)) aList.Add(p);
if (p.IsFlagSet(Extensions.ParticipantType.MOORING)) mList.Add(p);
if (p.IsFlagSet(Extensions.ParticipantType.PILOT)) pList.Add(p);
if (p.IsFlagSet(Extensions.ParticipantType.TUG)) tList.Add(p);
if (p.IsFlagSet(Extensions.ParticipantType.TERMINAL)) terList.Add(p);
}
this.comboBoxAgency.ItemsSource = aList;
this.comboBoxMooring.ItemsSource = mList;
this.comboBoxPilot.ItemsSource = pList;
this.comboBoxTug.ItemsSource = tList;
this.comboBoxTerminal.ItemsSource = terList;
this.comboBoxShip.ItemsSource = Ships;
this.comboBoxCategories.ItemsSource = Enum.GetValues(typeof(Extensions.TypeEnum));
this.comboBoxArrivalBerth.ItemsSource = this.Berths;
this.comboBoxDepartureBerth.ItemsSource = this.Berths;
this.CopyToControls();
}
private void buttonOK_Click(object sender, RoutedEventArgs e)
{
this.CopyToModel();
this.DialogResult = true;
this.Close();
}
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.DialogResult= false;
this.Close();
}
private void comboBoxShip_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.buttonOK.IsEnabled = this.comboBoxShip.SelectedItem != null;
}
#endregion
#region private methods
private void CopyToModel()
{
this.Shipcall.Type = (int) this.comboBoxCategories.SelectedItem;
this.Shipcall.Eta = this.datePickerETA.Value ?? DateTime.Now;
this.Shipcall.Voyage = this.textBoxVoyage.Text.Trim();
this.Shipcall.Etd = this.datePickerETD.Value ?? DateTime.Now.AddDays(1);
this.Shipcall.Anchored = this.checkBoxAnchored.IsChecked;
this.Shipcall.ShipId = ((Ship)this.comboBoxShip.SelectedItem).Id;
this.Shipcall.ArrivalBerthId = (this.comboBoxArrivalBerth.SelectedItem != null) ? ((Berth)this.comboBoxArrivalBerth.SelectedItem).Id : null;
this.Shipcall.DepartureBerthId = (this.comboBoxDepartureBerth.SelectedItem != null) ? ((Berth)this.comboBoxDepartureBerth.SelectedItem).Id : null;
this.Shipcall.Bunkering = this.checkBoxBunkering.IsChecked;
this.Shipcall.Canceled = this.checkBoxCanceled.IsChecked;
this.Shipcall.Draft = (float?) this.doubleUpDownDraft.Value;
this.Shipcall.MooredLock = this.checkBoxMooredLock.IsChecked;
this.Shipcall.RainSensitiveCargo = this.checkBoxRainsensitiveCargo.IsChecked;
this.Shipcall.PilotRequired = this.checkBoxPilotRequired.IsChecked;
this.Shipcall.ReplenishingLock = this.checkBoxReplenishingLock.IsChecked;
this.Shipcall.ReplenishingTerminal = this.checkBoxReplenishingTerminal.IsChecked;
this.Shipcall.RecommendedTugs = this.integerUpDownRecommendedTugs.Value;
this.Shipcall.TidalWindowFrom = this.datePickerTidalWindowFrom.Value;
this.Shipcall.TidalWindowTo = this.datePickerTidalWindowTo.Value;
this.Shipcall.TugRequired = this.checkBoxTugRequired.IsChecked;
if(this.comboBoxPierside.SelectedIndex >= 0)
{
this.Shipcall.PierSide = (this.comboBoxPierside.SelectedIndex == 0) ? true : false;
}
// remove all and add selected participants
this.Shipcall.Participants.Clear();
Participant? participant;
participant = (Participant?) this.comboBoxAgency.SelectedItem;
if (participant != null) this.Shipcall.Participants.Add(participant.Id);
participant = (Participant?) this.comboBoxMooring.SelectedItem;
if (participant != null) this.Shipcall.Participants.Add(participant.Id);
participant = (Participant?) this.comboBoxPilot.SelectedItem;
if (participant != null) this.Shipcall.Participants.Add(participant.Id);
participant = (Participant?) this.comboBoxTerminal.SelectedItem;
if (participant != null) this.Shipcall.Participants.Add(participant.Id);
participant = (Participant?) this.comboBoxTug.SelectedItem;
if (participant != null) this.Shipcall.Participants.Add(participant.Id);
// BSMD and port authority are always added
foreach(Participant p in Participants)
{
if(p.Type == (int) Extensions.ParticipantType.PORT_ADMINISTRATION) this.Shipcall.Participants.Add(p.Id);
if (p.Type == (int)Extensions.ParticipantType.BSMD) this.Shipcall.Participants.Add(p.Id);
}
}
private void CopyToControls()
{
if (this.Shipcall == null) return;
this.comboBoxCategories.SelectedItem = (Extensions.TypeEnum) this.Shipcall.Type;
if(this.Shipcall.Eta != DateTime.MinValue)
this.datePickerETA.Value = this.Shipcall.Eta;
this.textBoxVoyage.Text = this.Shipcall.Voyage;
this.datePickerETD.Value = this.Shipcall.Etd;
this.checkBoxAnchored.IsChecked = this.Shipcall.Anchored;
this.comboBoxShip.SelectedValue = this.Shipcall.ShipId;
this.comboBoxArrivalBerth.SelectedValue = this.Shipcall.ArrivalBerthId;
this.comboBoxDepartureBerth.SelectedValue = this.Shipcall.DepartureBerthId;
this.checkBoxBunkering.IsChecked = this.Shipcall.Bunkering;
this.checkBoxCanceled.IsChecked = this.Shipcall.Canceled;
this.doubleUpDownDraft.Value = this.Shipcall.Draft;
this.checkBoxMooredLock.IsChecked = this.Shipcall.MooredLock;
this.checkBoxRainsensitiveCargo.IsChecked = this.Shipcall.RainSensitiveCargo;
this.checkBoxPilotRequired.IsChecked = this.Shipcall.PilotRequired;
this.checkBoxReplenishingLock.IsChecked = this.Shipcall.ReplenishingLock;
this.checkBoxReplenishingTerminal.IsChecked = this.Shipcall.ReplenishingTerminal;
this.integerUpDownRecommendedTugs.Value = this.Shipcall.RecommendedTugs;
this.datePickerTidalWindowFrom.Value = this.Shipcall.TidalWindowFrom;
this.datePickerTidalWindowTo.Value = this.Shipcall.TidalWindowTo;
this.checkBoxTugRequired.IsChecked = this.Shipcall.TugRequired;
if(this.Shipcall.PierSide.HasValue)
{
if (this.Shipcall.PierSide.Value) this.comboBoxPierside.SelectedIndex = 0;
else this.comboBoxPierside.SelectedIndex = 1;
}
if (this.Shipcall.Participants == null) this.Shipcall.Participants = new();
foreach(int participant_id in this.Shipcall.Participants)
{
if (((List<Participant>)this.comboBoxAgency.ItemsSource).Any(x => x.Id == participant_id)) this.comboBoxAgency.SelectedValue = participant_id;
if (((List<Participant>)this.comboBoxMooring.ItemsSource).Any(x => x.Id == participant_id)) this.comboBoxMooring.SelectedValue = participant_id;
if (((List<Participant>)this.comboBoxPilot.ItemsSource).Any(x => x.Id == participant_id)) this.comboBoxPilot.SelectedValue = participant_id;
if (((List<Participant>)this.comboBoxTerminal.ItemsSource).Any(x => x.Id == participant_id)) this.comboBoxTerminal.SelectedValue = participant_id;
if (((List<Participant>)this.comboBoxTug.ItemsSource).Any(x => x.Id == participant_id)) this.comboBoxTug.SelectedValue = participant_id;
}
}
#endregion
}
}

View File

@ -0,0 +1,55 @@
<Window x:Class="BreCalClient.EditTimesControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BreCalClient"
xmlns:p = "clr-namespace:BreCalClient.Resources"
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="{x:Static p:Resources.textEditTimes}" Height="320" Width="400" Loaded="Window_Loaded" ResizeMode="NoResize" Icon="Resources/containership.ico">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".25*" />
<ColumnDefinition Width=".75*" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="56" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="2" Content="{x:Static p:Resources.textFixed}" />
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static p:Resources.textETABerth}" HorizontalContentAlignment="Right" />
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static p:Resources.textETDBerth}" HorizontalContentAlignment="Right" />
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static p:Resources.textLockTime}" HorizontalContentAlignment="Right" />
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static p:Resources.textZoneEntryTime}" HorizontalContentAlignment="Right" />
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static p:Resources.textOperationsStart}" HorizontalContentAlignment="Right" />
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static p:Resources.textOperationsEnd}" HorizontalContentAlignment="Right" />
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static p:Resources.textRemarks}" HorizontalContentAlignment="Right" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="1" Grid.Column="1" Margin="2" Name="datePickerETABerth" />
<CheckBox IsEnabled="False" Grid.Row="1" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxEtaBerthFixed" VerticalAlignment="Center" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="2" Grid.Column="1" Margin="2" Name="datePickerETDBerth" />
<CheckBox IsEnabled="False" Grid.Row="2" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxEtDBerthFixed" VerticalAlignment="Center" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="3" Grid.Column="1" Margin="2" Name="datePickerLockTime" />
<CheckBox IsEnabled="False" Grid.Row="3" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxLockTimeFixed" VerticalAlignment="Center" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="4" Grid.Column="1" Margin="2" Name="datePickerZoneEntry" />
<CheckBox IsEnabled="False" Grid.Row="4" Grid.Column="2" Margin="4,0,0,0" Name="checkBoxZoneEntryFixed" VerticalAlignment="Center" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="5" Grid.Column="1" Margin="2" Name="datePickerOperationStart" />
<xctk:DateTimePicker IsEnabled="False" Grid.Row="6" Grid.Column="1" Margin="2" Name="datePickerOperationEnd" />
<TextBox Grid.Row="7" Grid.Column="1" Margin="2" Name="textBoxRemarks" TextWrapping="Wrap" AcceptsReturn="True" SpellCheck.IsEnabled="True" AcceptsTab="True" />
<StackPanel Grid.Row="8" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Width= "80" Margin="2" Content="{x:Static p:Resources.textOK}" x:Name="buttonOK" Click="buttonOK_Click" />
<Button Width="80" Margin="2" Content="{x:Static p:Resources.textCancel}" x:Name="buttonCancel" Click="buttonCancel_Click"/>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,114 @@
// Copyright (c) 2023 schick Informatik
// Description: Single dialog to edit times for all participant types
// (we might use different controls at a later time)
//
using BreCalClient.misc.Model;
using System.Windows;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for EditTimesControl.xaml
/// </summary>
public partial class EditTimesControl : Window
{
#region Construction
public EditTimesControl()
{
InitializeComponent();
}
#endregion
#region Properties
public Times Times { get; set; } = new();
internal Extensions.ParticipantType ParticipantType { get; set; } = Extensions.ParticipantType.NONE;
#endregion
#region event handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.CopyToControls();
// enable controls according to participant type
this.datePickerETABerth.IsEnabled = App.Participant.IsFlagSet(Extensions.ParticipantType.AGENCY) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.MOORING) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.PILOT) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.PORT_ADMINISTRATION) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.TUG);
this.checkBoxEtaBerthFixed.IsEnabled = this.datePickerETABerth.IsEnabled;
this.datePickerETDBerth.IsEnabled = this.datePickerETABerth.IsEnabled;
this.checkBoxEtDBerthFixed.IsEnabled = this.datePickerETABerth.IsEnabled;
this.datePickerLockTime.IsEnabled = App.Participant.IsFlagSet(Extensions.ParticipantType.AGENCY) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.MOORING) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.PORT_ADMINISTRATION);
this.checkBoxLockTimeFixed.IsEnabled = this.datePickerLockTime.IsEnabled;
this.datePickerZoneEntry.IsEnabled = App.Participant.IsFlagSet(Extensions.ParticipantType.AGENCY) ||
App.Participant.IsFlagSet(Extensions.ParticipantType.PILOT);
this.checkBoxZoneEntryFixed.IsEnabled = this.datePickerZoneEntry.IsEnabled;
this.datePickerOperationStart.IsEnabled = App.Participant.IsFlagSet(Extensions.ParticipantType.TERMINAL);
this.datePickerOperationEnd.IsEnabled = App.Participant.IsFlagSet(Extensions.ParticipantType.TERMINAL);
}
private void buttonOK_Click(object sender, RoutedEventArgs e)
{
this.CopyToModel();
this.DialogResult = true;
this.Close();
}
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
#endregion
#region private methods
private void CopyToModel()
{
this.Times.Remarks = this.textBoxRemarks.Text.Trim().Truncate(512);
this.Times.EtaBerth = this.datePickerETABerth.Value;
this.Times.EtdBerth = this.datePickerETDBerth.Value;
this.Times.LockTime = this.datePickerLockTime.Value;
this.Times.ZoneEntry = this.datePickerZoneEntry.Value;
this.Times.OperationsStart = this.datePickerOperationStart.Value;
this.Times.OperationsEnd = this.datePickerOperationEnd.Value;
this.Times.EtaBerthFixed = this.checkBoxEtaBerthFixed.IsChecked;
this.Times.EtdBerthFixed = this.checkBoxEtDBerthFixed.IsChecked;
this.Times.LockTimeFixed = this.checkBoxLockTimeFixed.IsChecked;
this.Times.ZoneEntryFixed = this.checkBoxZoneEntryFixed.IsChecked;
}
private void CopyToControls()
{
this.textBoxRemarks.Text = this.Times.Remarks;
this.datePickerETABerth.Value = this.Times.EtaBerth;
this.datePickerETDBerth.Value = this.Times.EtdBerth;
this.datePickerLockTime.Value = this.Times.LockTime;
this.datePickerZoneEntry.Value = this.Times.ZoneEntry;
this.datePickerOperationStart.Value = this.Times.OperationsStart;
this.datePickerOperationEnd.Value = this.Times.OperationsEnd;
this.checkBoxEtaBerthFixed.IsChecked = this.Times.EtaBerthFixed;
this.checkBoxEtDBerthFixed.IsChecked = this.Times.EtdBerthFixed;
this.checkBoxLockTimeFixed.IsChecked = this.Times.LockTimeFixed;
this.checkBoxZoneEntryFixed.IsChecked = this.Times.ZoneEntryFixed;
}
#endregion
}
}

View File

@ -0,0 +1,86 @@
// Copyright (c) 2023 schick Informatik
// Description: some helpers
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BreCalClient
{
internal static class Extensions
{
#region Enum
/// <summary>
/// Copied from models clunky I know
/// </summary>
[Flags]
public enum ParticipantType
{
[Description("not assigned")]
NONE = 0,
[Description("BSMD")]
BSMD = 1,
[Description("Terminal")]
TERMINAL = 2,
[Description("Lotsen")]
PILOT = 4,
[Description("Agentur")]
AGENCY = 8,
[Description("Festmacher")]
MOORING = 16,
[Description("Hafenamt")]
PORT_ADMINISTRATION = 32,
[Description("Schlepper")]
TUG = 64,
}
/// <summary>
/// Should actually be defined in yaml
/// </summary>
public enum TypeEnum
{
Incoming = 1,
Outgoing = 2,
Shifting = 3
}
#endregion
#region public helper
public static bool IsFlagSet(this Participant participant, ParticipantType flag)
{
return (participant.Type & (uint)flag) != 0;
}
public static void SetFlag(this Participant participant, bool value, ParticipantType flag)
{
if (value) participant.Type |= (int)flag;
else participant.Type &= (int)~flag;
}
public static string Truncate(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value)) return value;
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
public static string TruncateDots(this string value, int maxLength)
{
if(string.IsNullOrEmpty(value)) return value;
if (value.Length <= maxLength) return value;
if (value.Length > (maxLength + 1)) return $"{value.Substring(0, maxLength)}..";
return value.Substring(0, maxLength);
}
#endregion
}
}

View File

@ -0,0 +1,133 @@
<Window x:Class="BreCalClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BreCalClient"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p = "clr-namespace:BreCalClient.Resources"
mc:Ignorable="d"
Title="{DynamicResource textApplicationTitle}" Height="450" Width="800" Loaded="Window_Loaded" Closing="Window_Closing" Icon="Resources/containership.ico">
<Window.Resources>
<local:BoolToIndexConverter x:Key="boolToIndexConverter" />
</Window.Resources>
<xctk:BusyIndicator Name="busyIndicator" IsBusy="True">
<xctk:BusyIndicator.ProgressBarStyle>
<Style TargetType="ProgressBar">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</xctk:BusyIndicator.ProgressBarStyle>
<xctk:BusyIndicator.BusyContent>
<Grid Width="320">
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Label Content="{x:Static p:Resources.textUserlogin}" Grid.Row="0" Grid.ColumnSpan="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
<Label Content="{x:Static p:Resources.textUsername}" Grid.Row="1" VerticalContentAlignment="Center" />
<Label Content="{x:Static p:Resources.textPassword}" Grid.Row="2" VerticalContentAlignment="Center" />
<TextBox Name="textUsername" Grid.Row="1" Grid.Column="1" Margin="2" VerticalContentAlignment="Center" />
<PasswordBox Name="textPassword" Grid.Row="2" Grid.Column="1" Margin="2" VerticalContentAlignment="Center" PasswordChar="*"/>
<Label Name="labelLoginResult" Grid.Row="3" Grid.ColumnSpan="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
<Button Name="buttonLogin" Content="{x:Static p:Resources.textLogin}" Grid.Row="4" Grid.Column="0" Margin="2" Click="buttonLogin_Click" IsDefault="True" />
<Button Name="buttonExit" Content="{x:Static p:Resources.textExit}" Grid.Row="4" Grid.Column="1" Margin="2" Click="buttonExit_Click" />
</Grid>
</xctk:BusyIndicator.BusyContent>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="28" />
<RowDefinition Height="34" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<local:SearchFilterControl Grid.Row="0" x:Name="searchFilterControl" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".2*" />
<ColumnDefinition Width=".6*" />
</Grid.ColumnDefinitions>
<Button Margin="2" Grid.Column="0" Content="{x:Static p:Resources.textNewDots}" x:Name="buttonNew" Visibility="Hidden" Click="buttonNew_Click" Background="Transparent"/>
<Label Content="{x:Static p:Resources.textSortOrder}" Grid.Column="1" HorizontalContentAlignment="Right"/>
<ComboBox x:Name="comboBoxSortOrder" Margin="2" Grid.Column="2" />
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Background="#203864" Foreground="White" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="1" Background="#203864" Foreground="White" Content="Agent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="2" Background="#203864" Foreground="White" Content="Festmacher" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="3" Background="#203864" Foreground="White" Content="Hafenamt" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="4" Background="#203864" Foreground="White" Content="Lotsen" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="5" Background="#203864" Foreground="White" Content="Schlepper" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
<Label Grid.Column="6" Background="#203864" Foreground="White" Content="Terminal" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></Label>
</Grid>
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="stackPanel"/>
</ScrollViewer>
<StatusBar Grid.Row="4">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="120" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem Grid.Column="0">
<TextBlock Name="labelGeneralStatus" FontSize="9"></TextBlock>
</StatusBarItem>
<Separator Grid.Column="1"/>
<StatusBarItem Grid.Column="2">
<TextBlock Name="labelVersion"></TextBlock>
</StatusBarItem>
<Separator Grid.Column="3"/>
<StatusBarItem Grid.Column="4">
<TextBlock Name="labelUsername"></TextBlock>
</StatusBarItem>
<Separator Grid.Column="5"/>
<StatusBarItem Grid.Column="6">
<Button x:Name="buttonInfo" Content="?" Click="buttonInfo_Click" Width="20" />
</StatusBarItem>
<Separator Grid.Column="7"/>
<StatusBarItem Grid.Column="8">
<TextBlock Name="labelStatusBar"></TextBlock>
</StatusBarItem>
<Separator Grid.Column="9"/>
<StatusBarItem Grid.Column="10">
<ProgressBar Name="generalProgressStatus" Width="90" Height="16"/>
</StatusBarItem>
</StatusBar>
</Grid>
</xctk:BusyIndicator>
</Window>

View File

@ -0,0 +1,389 @@
// Copyright (c) 2023 schick Informatik
// Description: Bremen calling main window
//
using BreCalClient.misc.Api;
using BreCalClient.misc.Client;
using BreCalClient.misc.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Fields
private const int SHIPCALL_UPDATE_INTERVAL_SECONDS = 30;
private readonly DefaultApi _api;
private readonly ObservableCollection<ShipcallControlModel> _controlModels = new();
private List<Ship> _ships = new();
private readonly ConcurrentDictionary<int, Ship> _shipLookupDict = new();
private List<Berth> _berths = new();
private readonly ConcurrentDictionary<int, Berth> _berthLookupDict = new();
private List<Participant> _participants = new();
private readonly Dictionary<int, Participant> _participantLookupDict = new();
private readonly Dictionary<int, ShipcallControl> _shipCallControlDict = new();
private readonly CancellationTokenSource _tokenSource = new();
private LoginResult? _loginResult;
#endregion
#region Enums
private enum ConnectionStatus
{
UNDEFINED,
SUCCESSFUL,
FAILED
}
#endregion
#region Construction
public MainWindow()
{
InitializeComponent();
_api = new DefaultApi();
_api.Configuration.ApiKeyPrefix["Authorization"] = "Bearer";
}
#endregion
#region event handler
private void Window_Loaded(object sender, RoutedEventArgs e)
{
labelGeneralStatus.Text = $"Connection {ConnectionStatus.UNDEFINED}";
labelVersion.Text = "V. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_tokenSource.Cancel();
}
private async void buttonLogin_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(this.textPassword.Password) || string.IsNullOrEmpty(this.textUsername.Text))
{
this.labelLoginResult.Content = Application.Current.FindResource("textUserNamePasswordEmpty").ToString();
return;
}
Credentials credentials = new(username: textUsername.Text.Trim(),
password: textPassword.Password.Trim());
try
{
_loginResult = await _api.LoginPostAsync(credentials);
if (_loginResult != null)
{
if (_loginResult.Id > 0)
{
this.busyIndicator.IsBusy = false;
this._api.Configuration.ApiKey["Authorization"] = _loginResult.Token;
this.LoadStaticLists();
this.labelUsername.Text = $"{_loginResult.FirstName} {_loginResult.LastName}";
}
}
labelGeneralStatus.Text = $"Connection {ConnectionStatus.SUCCESSFUL}";
}
catch (ApiException ex)
{
this.labelLoginResult.Content = ex.Message;
labelGeneralStatus.Text = $"Connection {ConnectionStatus.FAILED}";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
labelGeneralStatus.Text = $"Connection {ConnectionStatus.FAILED}";
}
}
private void buttonExit_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void buttonNew_Click(object sender, RoutedEventArgs e)
{
EditShipcallControl esc = new()
{
Participants = this._participants,
Ships = this._ships,
Berths = this._berths
};
if (esc.ShowDialog() ?? false)
{
// create UI & save new dialog model
this.UpdateShipcallUI(esc.Shipcall, new List<Times>());
this._api.ShipcallsPost(esc.Shipcall);
}
}
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
AboutDialog ad = new();
ad.ChangePasswordRequested += async (oldPw, newPw) =>
{
if (_loginResult != null)
{
UserDetails ud = new()
{
Id = _loginResult.Id,
FirstName = _loginResult.FirstName,
LastName = _loginResult.LastName,
UserPhone = _loginResult.UserPhone,
OldPassword = oldPw,
NewPassword = newPw
};
try
{
await _api.UserPutAsync(ud);
}
catch (Exception ex)
{
this.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}));
}
}
};
ad.ShowDialog();
}
#endregion
#region private methods
private async void LoadStaticLists()
{
this._berths = await _api.BerthsGetAsync();
foreach(var berth in this._berths)
_berthLookupDict[berth.Id] = berth;
this.searchFilterControl.SetBerths(this._berths);
this._ships = await _api.ShipsGetAsync();
foreach(var ship in this._ships)
_shipLookupDict[ship.Id] = ship;
this._participants = await _api.ParticipantsGetAsync();
List<Participant> agencies = new();
foreach (Participant participant in this._participants)
{
this._participantLookupDict[participant.Id] = participant;
if (_loginResult?.ParticipantId == participant.Id)
{
App.Participant = participant;
EnableControlsForParticipant();
}
if(participant.IsFlagSet(Extensions.ParticipantType.AGENCY))
agencies.Add(participant);
}
this.searchFilterControl.SetAgencies(agencies);
_ = Task.Run(() => RefreshShipcalls());
}
private void EnableControlsForParticipant()
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.BSMD))
this.buttonNew.Visibility = Visibility.Visible;
}
public async Task RefreshShipcalls()
{
while (!_tokenSource.Token.IsCancellationRequested)
{
List<Shipcall>? shipcalls = null;
try
{
shipcalls = await _api.ShipcallsGetAsync();
this.Dispatcher.Invoke(new Action(() =>
{
labelGeneralStatus.Text = $"Connection {ConnectionStatus.SUCCESSFUL}";
labelGeneralStatus.Text = $"Ok";
}));
}
catch (Exception ex)
{
this.Dispatcher.Invoke(new Action(() =>
{
labelGeneralStatus.Text = $"Connection {ConnectionStatus.FAILED}";
labelStatusBar.Text = ex.Message;
}));
}
if (shipcalls != null)
{
foreach (Shipcall shipcall in shipcalls)
{
List<Times> currentTimes = await _api.TimesGetAsync(shipcall.Id);
this.UpdateShipcallUI(shipcall, currentTimes);
}
List<ShipcallControl> removeList = new();
foreach (ShipcallControlModel scm in this._controlModels)
{
if (shipcalls.Find(s => s.Id == scm.Shipcall?.Id) == null) // the model is no longer in the search result
{
if((scm.Shipcall != null) && this._shipCallControlDict.ContainsKey(scm.Shipcall.Id))
{
this.Dispatcher.Invoke((Action)(() =>
{
this.stackPanel.Children.Remove(this._shipCallControlDict[scm.Shipcall.Id]);
}));
this._shipCallControlDict.Remove(scm.Shipcall.Id);
}
}
}
}
await Task.Delay(TimeSpan.FromSeconds(SHIPCALL_UPDATE_INTERVAL_SECONDS), _tokenSource.Token);
}
}
private void UpdateShipcallUI(Shipcall shipcall, List<Times> times)
{
ShipcallControlModel? selectedSCMModel = null;
foreach (ShipcallControlModel scm in this._controlModels)
{
if (scm.Shipcall?.Id == shipcall.Id)
{
selectedSCMModel = scm;
break;
}
}
if (selectedSCMModel != null)
{
selectedSCMModel.Shipcall = shipcall;
selectedSCMModel.Times = times;
}
else
{
// no: create new entry
selectedSCMModel = new()
{
Shipcall = shipcall,
Times = times
};
if (this._shipLookupDict.ContainsKey(shipcall.ShipId))
selectedSCMModel.Ship = this._shipLookupDict[shipcall.ShipId];
if (this._berthLookupDict.ContainsKey(shipcall.ArrivalBerthId ?? 0))
selectedSCMModel.Berth = this._berthLookupDict[shipcall.ArrivalBerthId ?? 0].Name;
_controlModels.Add(selectedSCMModel);
this.Dispatcher.Invoke(new Action(() =>
{
ShipcallControl sc = new()
{
Height = 120,
ShipcallControlModel = selectedSCMModel,
ParticipantDict = _participantLookupDict
};
sc.EditTimesRequested += Sc_EditTimesRequested;
sc.EditRequested += Sc_EditRequested;
this.stackPanel.Children.Add(sc);
this._shipCallControlDict[shipcall.Id] = sc;
}));
}
selectedSCMModel.AssignParticipants(this._participants);
this.Dispatcher.Invoke((Action)(() =>
{
this._shipCallControlDict[shipcall.Id].RefreshData();
}));
}
private async void Sc_EditRequested(ShipcallControl obj)
{
Shipcall? sc = obj.ShipcallControlModel?.Shipcall;
if (sc != null)
{
EditShipcallControl esc = new()
{
Shipcall = sc,
Ships = _ships,
Participants = _participants,
Berths = _berths
};
if(esc.ShowDialog() ?? false)
{
try
{
await _api.ShipcallsPutAsync(sc);
obj.RefreshData();
}
catch (Exception ex)
{
ShowErrorDialog(ex.Message, "Error saving edited shipcall");
}
}
}
}
private async void Sc_EditTimesRequested(ShipcallControl obj, Times? times)
{
// show a dialog that lets the user create / update times for the given shipcall
EditTimesControl etc = new();
bool wasEdit = false;
if (times != null)
{
etc.Times = times;
wasEdit = true;
}
if(etc.ShowDialog() ?? false)
{
try
{
if (wasEdit)
{
await _api.TimesPutAsync(etc.Times);
}
else
{
etc.Times.ParticipantId = App.Participant.Id;
if ((obj.ShipcallControlModel != null) && (obj.ShipcallControlModel.Shipcall != null))
{
etc.Times.ShipcallId = obj.ShipcallControlModel.Shipcall.Id;
}
await _api.TimesPostAsync(etc.Times);
obj.ShipcallControlModel?.Times.Add(etc.Times);
}
obj.RefreshData();
}
catch (Exception ex)
{
ShowErrorDialog(ex.Message, "Error saving times");
}
}
}
private void ShowErrorDialog(string message, string caption)
{
Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show(message, caption, MessageBoxButton.OK, MessageBoxImage.Error);
}));
}
#endregion
}
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.3.0.0</ApplicationVersion>
<BootstrapperEnabled>False</BootstrapperEnabled>
<Configuration>Release</Configuration>
<CreateWebPageOnPublish>True</CreateWebPageOnPublish>
<GenerateManifests>true</GenerateManifests>
<Install>True</Install>
<InstallFrom>Web</InstallFrom>
<InstallUrl>https://www.bsmd-emswe.eu/client/</InstallUrl>
<IsRevisionIncremented>False</IsRevisionIncremented>
<IsWebBootstrapper>True</IsWebBootstrapper>
<MapFileExtensions>True</MapFileExtensions>
<OpenBrowserOnPublish>False</OpenBrowserOnPublish>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net6.0-windows\app.publish\</PublishDir>
<PublishUrl>bin\publish\</PublishUrl>
<PublishProtocol>ClickOnce</PublishProtocol>
<PublishReadyToRun>False</PublishReadyToRun>
<PublishSingleFile>False</PublishSingleFile>
<SelfContained>False</SelfContained>
<SignatureAlgorithm>(none)</SignatureAlgorithm>
<SignManifests>False</SignManifests>
<TargetFramework>net6.0-windows</TargetFramework>
<UpdateEnabled>True</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateRequired>False</UpdateRequired>
<WebPageFileName>Publish.html</WebPageFileName>
<CreateDesktopShortcut>True</CreateDesktopShortcut>
<ErrorReportUrl>https://www.bsmd-emswe.eu/</ErrorReportUrl>
<ProductName>BreCalClient</ProductName>
<PublisherName>Informatikbüro Daniel Schick</PublisherName>
<SuiteName>Bremen calling client</SuiteName>
<SupportUrl>https://www.bsmd-emswe.eu/</SupportUrl>
</PropertyGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.NetCore.DesktopRuntime.6.0.x64">
<Install>true</Install>
<ProductName>.NET Desktop Runtime 6.0.16 (x64)</ProductName>
</BootstrapperPackage>
</ItemGroup>
</Project>

View File

@ -0,0 +1,840 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace BreCalClient.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BreCalClient.Resources.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] arrow_down_green {
get {
object obj = ResourceManager.GetObject("arrow_down_green", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] arrow_down_red {
get {
object obj = ResourceManager.GetObject("arrow_down_red", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] arrow_right_blue {
get {
object obj = ResourceManager.GetObject("arrow_right_blue", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] arrow_up_green {
get {
object obj = ResourceManager.GetObject("arrow_up_green", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] arrow_up_red {
get {
object obj = ResourceManager.GetObject("arrow_up_red", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] clipboard {
get {
object obj = ResourceManager.GetObject("clipboard", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] clock {
get {
object obj = ResourceManager.GetObject("clock", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] containership {
get {
object obj = ResourceManager.GetObject("containership", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] containership1 {
get {
object obj = ResourceManager.GetObject("containership1", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] emergency_stop_button {
get {
object obj = ResourceManager.GetObject("emergency_stop_button", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] logo_bremen_calling {
get {
object obj = ResourceManager.GetObject("logo_bremen_calling", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ship2 {
get {
object obj = ResourceManager.GetObject("ship2", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Agencies.
/// </summary>
public static string textAgencies {
get {
return ResourceManager.GetString("textAgencies", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Agency.
/// </summary>
public static string textAgency {
get {
return ResourceManager.GetString("textAgency", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Anchored.
/// </summary>
public static string textAnchored {
get {
return ResourceManager.GetString("textAnchored", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Arrival terminal.
/// </summary>
public static string textArrivalTerminal {
get {
return ResourceManager.GetString("textArrivalTerminal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Berth.
/// </summary>
public static string textBerth {
get {
return ResourceManager.GetString("textBerth", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Berths.
/// </summary>
public static string textBerths {
get {
return ResourceManager.GetString("textBerths", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Bunkering.
/// </summary>
public static string textBunkering {
get {
return ResourceManager.GetString("textBunkering", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Callsign.
/// </summary>
public static string textCallsign {
get {
return ResourceManager.GetString("textCallsign", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cancel.
/// </summary>
public static string textCancel {
get {
return ResourceManager.GetString("textCancel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cancelled.
/// </summary>
public static string textCancelled {
get {
return ResourceManager.GetString("textCancelled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Categories.
/// </summary>
public static string textCategories {
get {
return ResourceManager.GetString("textCategories", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Change.
/// </summary>
public static string textChange {
get {
return ResourceManager.GetString("textChange", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Change password.
/// </summary>
public static string textChangePassword {
get {
return ResourceManager.GetString("textChangePassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Close.
/// </summary>
public static string textClose {
get {
return ResourceManager.GetString("textClose", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Departure terminal.
/// </summary>
public static string textDepartureTerminal {
get {
return ResourceManager.GetString("textDepartureTerminal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Draft.
/// </summary>
public static string textDraft {
get {
return ResourceManager.GetString("textDraft", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Edit ship call.
/// </summary>
public static string textEditShipcall {
get {
return ResourceManager.GetString("textEditShipcall", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Edit times.
/// </summary>
public static string textEditTimes {
get {
return ResourceManager.GetString("textEditTimes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enter keyword.
/// </summary>
public static string textEnterKeyword {
get {
return ResourceManager.GetString("textEnterKeyword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ETA berth.
/// </summary>
public static string textETABerth {
get {
return ResourceManager.GetString("textETABerth", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ETD berth.
/// </summary>
public static string textETDBerth {
get {
return ResourceManager.GetString("textETDBerth", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exit.
/// </summary>
public static string textExit {
get {
return ResourceManager.GetString("textExit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fixed.
/// </summary>
public static string textFixed {
get {
return ResourceManager.GetString("textFixed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to from.
/// </summary>
public static string textFrom {
get {
return ResourceManager.GetString("textFrom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Interval.
/// </summary>
public static string textInterval {
get {
return ResourceManager.GetString("textInterval", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to L/W.
/// </summary>
public static string textLengthWidth {
get {
return ResourceManager.GetString("textLengthWidth", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lock time.
/// </summary>
public static string textLockTime {
get {
return ResourceManager.GetString("textLockTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Login.
/// </summary>
public static string textLogin {
get {
return ResourceManager.GetString("textLogin", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Moored in lock.
/// </summary>
public static string textMooredLock {
get {
return ResourceManager.GetString("textMooredLock", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Mooring.
/// </summary>
public static string textMooring {
get {
return ResourceManager.GetString("textMooring", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New...
/// </summary>
public static string textNewDots {
get {
return ResourceManager.GetString("textNewDots", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New password.
/// </summary>
public static string textNewPassword {
get {
return ResourceManager.GetString("textNewPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not rotated.
/// </summary>
public static string textNotRotated {
get {
return ResourceManager.GetString("textNotRotated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to OK.
/// </summary>
public static string textOK {
get {
return ResourceManager.GetString("textOK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Old password.
/// </summary>
public static string textOldPassword {
get {
return ResourceManager.GetString("textOldPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Operations end.
/// </summary>
public static string textOperationsEnd {
get {
return ResourceManager.GetString("textOperationsEnd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Operations start.
/// </summary>
public static string textOperationsStart {
get {
return ResourceManager.GetString("textOperationsStart", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Participants.
/// </summary>
public static string textParticipants {
get {
return ResourceManager.GetString("textParticipants", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password.
/// </summary>
public static string textPassword {
get {
return ResourceManager.GetString("textPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pier side.
/// </summary>
public static string textPierside {
get {
return ResourceManager.GetString("textPierside", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pilot.
/// </summary>
public static string textPilot {
get {
return ResourceManager.GetString("textPilot", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pilot required.
/// </summary>
public static string textPilotRequired {
get {
return ResourceManager.GetString("textPilotRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rain sensitive cargo.
/// </summary>
public static string textRainSensitiveCargo {
get {
return ResourceManager.GetString("textRainSensitiveCargo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Recommended tugs.
/// </summary>
public static string textRecommendedTugs {
get {
return ResourceManager.GetString("textRecommendedTugs", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remarks.
/// </summary>
public static string textRemarks {
get {
return ResourceManager.GetString("textRemarks", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Repeat new password.
/// </summary>
public static string textRepeatNewPassword {
get {
return ResourceManager.GetString("textRepeatNewPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Replenishing lock.
/// </summary>
public static string textReplenishingLock {
get {
return ResourceManager.GetString("textReplenishingLock", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Replenishing terminal.
/// </summary>
public static string textReplenishingTerminal {
get {
return ResourceManager.GetString("textReplenishingTerminal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rotated.
/// </summary>
public static string textRotated {
get {
return ResourceManager.GetString("textRotated", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
public static string textSearch {
get {
return ResourceManager.GetString("textSearch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ship.
/// </summary>
public static string textShip {
get {
return ResourceManager.GetString("textShip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ship length.
/// </summary>
public static string textShipLength {
get {
return ResourceManager.GetString("textShipLength", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sort order.
/// </summary>
public static string textSortOrder {
get {
return ResourceManager.GetString("textSortOrder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Terminal.
/// </summary>
public static string textTerminal {
get {
return ResourceManager.GetString("textTerminal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tidal window.
/// </summary>
public static string textTidalWindow {
get {
return ResourceManager.GetString("textTidalWindow", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to to.
/// </summary>
public static string textTo {
get {
return ResourceManager.GetString("textTo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tug.
/// </summary>
public static string textTug {
get {
return ResourceManager.GetString("textTug", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tug required.
/// </summary>
public static string textTugRequired {
get {
return ResourceManager.GetString("textTugRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type.
/// </summary>
public static string textType {
get {
return ResourceManager.GetString("textType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to User login.
/// </summary>
public static string textUserlogin {
get {
return ResourceManager.GetString("textUserlogin", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to User name.
/// </summary>
public static string textUsername {
get {
return ResourceManager.GetString("textUsername", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Voyage.
/// </summary>
public static string textVoyage {
get {
return ResourceManager.GetString("textVoyage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Zone entry.
/// </summary>
public static string textZoneEntryTime {
get {
return ResourceManager.GetString("textZoneEntryTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_green {
get {
object obj = ResourceManager.GetObject("trafficlight_green", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_off {
get {
object obj = ResourceManager.GetObject("trafficlight_off", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_on {
get {
object obj = ResourceManager.GetObject("trafficlight_on", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_red {
get {
object obj = ResourceManager.GetObject("trafficlight_red", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_red_yellow {
get {
object obj = ResourceManager.GetObject("trafficlight_red_yellow", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] trafficlight_yellow {
get {
object obj = ResourceManager.GetObject("trafficlight_yellow", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] umbrella_closed {
get {
object obj = ResourceManager.GetObject("umbrella_closed", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] umbrella_open {
get {
object obj = ResourceManager.GetObject("umbrella_open", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] worker2 {
get {
object obj = ResourceManager.GetObject("worker2", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -0,0 +1,361 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="arrow_down_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_down_red.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_right_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_right_blue.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_up_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_up_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="clipboard" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>clipboard.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="clock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>clock.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="containership" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>containership.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="emergency_stop_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>emergency_stop_button.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="logo_bremen_calling" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>logo_bremen_calling.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ship2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>ship2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="textAgencies" xml:space="preserve">
<value>Agenturen</value>
</data>
<data name="textAgency" xml:space="preserve">
<value>Agentur</value>
</data>
<data name="textAnchored" xml:space="preserve">
<value>Ankerorder</value>
</data>
<data name="textArrivalTerminal" xml:space="preserve">
<value>Terminal Ankunft</value>
</data>
<data name="textBerth" xml:space="preserve">
<value>Liegeplatz</value>
</data>
<data name="textBerths" xml:space="preserve">
<value>Liegeplätze</value>
</data>
<data name="textBunkering" xml:space="preserve">
<value>Bunkeraufnahme</value>
</data>
<data name="textCallsign" xml:space="preserve">
<value>Rufzeichen</value>
</data>
<data name="textCancel" xml:space="preserve">
<value>Abbrechen</value>
</data>
<data name="textCancelled" xml:space="preserve">
<value>Annulliert</value>
</data>
<data name="textCategories" xml:space="preserve">
<value>Kategorien</value>
</data>
<data name="textChange" xml:space="preserve">
<value>Ändern</value>
</data>
<data name="textChangePassword" xml:space="preserve">
<value>Password ändern</value>
</data>
<data name="textClose" xml:space="preserve">
<value>Schliessen</value>
</data>
<data name="textDepartureTerminal" xml:space="preserve">
<value>Terminal Abfahrt</value>
</data>
<data name="textDraft" xml:space="preserve">
<value>Tiefgang</value>
</data>
<data name="textEditShipcall" xml:space="preserve">
<value>Schiffsanlauf bearbeiten</value>
</data>
<data name="textEditTimes" xml:space="preserve">
<value>Zeiten bearbeiten</value>
</data>
<data name="textETABerth" xml:space="preserve">
<value>ETA Liegeplatz</value>
</data>
<data name="textETDBerth" xml:space="preserve">
<value>ETD Liegeplatz</value>
</data>
<data name="textEnterKeyword" xml:space="preserve">
<value>Suchbegriff eingeben</value>
</data>
<data name="textExit" xml:space="preserve">
<value>Verlassen</value>
</data>
<data name="textFrom" xml:space="preserve">
<value>von</value>
</data>
<data name="textInterval" xml:space="preserve">
<value>Zeitraum</value>
</data>
<data name="textLengthWidth" xml:space="preserve">
<value>L/B</value>
</data>
<data name="textLogin" xml:space="preserve">
<value>Anmelden</value>
</data>
<data name="textFixed" xml:space="preserve">
<value>Fest</value>
</data>
<data name="textLockTime" xml:space="preserve">
<value>Zeit Schleuse</value>
</data>
<data name="textOperationsEnd" xml:space="preserve">
<value>Operation Ende</value>
</data>
<data name="textOperationsStart" xml:space="preserve">
<value>Operation Start</value>
</data>
<data name="textMooredLock" xml:space="preserve">
<value>Festmacher in Schleuse</value>
</data>
<data name="textMooring" xml:space="preserve">
<value>Festmacher</value>
</data>
<data name="textNewDots" xml:space="preserve">
<value>Neu..</value>
</data>
<data name="textNewPassword" xml:space="preserve">
<value>Neues Passwort</value>
</data>
<data name="textNotRotated" xml:space="preserve">
<value>Ungedreht</value>
</data>
<data name="textZoneEntryTime" xml:space="preserve">
<value>Reviereintritt</value>
</data>
<data name="textOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="textOldPassword" xml:space="preserve">
<value>Altes Passwort</value>
</data>
<data name="textParticipants" xml:space="preserve">
<value>Teilnehmer</value>
</data>
<data name="textPassword" xml:space="preserve">
<value>Passwort</value>
</data>
<data name="textPierside" xml:space="preserve">
<value>Anlegeseite</value>
</data>
<data name="textPilot" xml:space="preserve">
<value>Lotse</value>
</data>
<data name="textPilotRequired" xml:space="preserve">
<value>Lotsorder</value>
</data>
<data name="textRainSensitiveCargo" xml:space="preserve">
<value>Regensensitive Ladung</value>
</data>
<data name="textRecommendedTugs" xml:space="preserve">
<value>Anzahl Schlepper</value>
</data>
<data name="textRepeatNewPassword" xml:space="preserve">
<value>Neues Passwort wiederholen</value>
</data>
<data name="textReplenishingLock" xml:space="preserve">
<value>Versorgungsaufnahme Schleuse</value>
</data>
<data name="textReplenishingTerminal" xml:space="preserve">
<value>Versorgungsaufnahme Terminal</value>
</data>
<data name="textRotated" xml:space="preserve">
<value>Gedreht</value>
</data>
<data name="textSearch" xml:space="preserve">
<value>Suche</value>
</data>
<data name="textShip" xml:space="preserve">
<value>Schiff</value>
</data>
<data name="textShipLength" xml:space="preserve">
<value>Schiffslänge</value>
</data>
<data name="textSortOrder" xml:space="preserve">
<value>Sortierung</value>
</data>
<data name="textTerminal" xml:space="preserve">
<value>Terminal</value>
</data>
<data name="textTidalWindow" xml:space="preserve">
<value>Tidenfenster</value>
</data>
<data name="textTo" xml:space="preserve">
<value>bis</value>
</data>
<data name="textTug" xml:space="preserve">
<value>Schlepper</value>
</data>
<data name="textTugRequired" xml:space="preserve">
<value>Schlepperorder</value>
</data>
<data name="textType" xml:space="preserve">
<value>Typ</value>
</data>
<data name="textUserlogin" xml:space="preserve">
<value>Anmeldung</value>
</data>
<data name="textUsername" xml:space="preserve">
<value>Benutzername</value>
</data>
<data name="textVoyage" xml:space="preserve">
<value>Reise</value>
</data>
<data name="trafficlight_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_off" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_off.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_on" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_on.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_red.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_red_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_red_yellow.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_yellow.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="umbrella_closed" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>umbrella_closed.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="umbrella_open" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>umbrella_open.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="worker2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>worker2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -0,0 +1,373 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="arrow_down_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_down_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_down_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_down_red.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_right_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_right_blue.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_up_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_up_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_up_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>arrow_up_red.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="clipboard" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>clipboard.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="clock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>clock.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="containership" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>containership.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="containership1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>containership.ico;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="emergency_stop_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>emergency_stop_button.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="logo_bremen_calling" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>logo_bremen_calling.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ship2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>ship2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="textAgencies" xml:space="preserve">
<value>Agencies</value>
</data>
<data name="textAgency" xml:space="preserve">
<value>Agency</value>
</data>
<data name="textAnchored" xml:space="preserve">
<value>Anchored</value>
</data>
<data name="textArrivalTerminal" xml:space="preserve">
<value>Arrival terminal</value>
</data>
<data name="textBerth" xml:space="preserve">
<value>Berth</value>
</data>
<data name="textBerths" xml:space="preserve">
<value>Berths</value>
</data>
<data name="textBunkering" xml:space="preserve">
<value>Bunkering</value>
</data>
<data name="textCallsign" xml:space="preserve">
<value>Callsign</value>
</data>
<data name="textCancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="textCancelled" xml:space="preserve">
<value>Cancelled</value>
</data>
<data name="textCategories" xml:space="preserve">
<value>Categories</value>
</data>
<data name="textChange" xml:space="preserve">
<value>Change</value>
</data>
<data name="textChangePassword" xml:space="preserve">
<value>Change password</value>
</data>
<data name="textClose" xml:space="preserve">
<value>Close</value>
</data>
<data name="textDepartureTerminal" xml:space="preserve">
<value>Departure terminal</value>
</data>
<data name="textDraft" xml:space="preserve">
<value>Draft</value>
</data>
<data name="textEditShipcall" xml:space="preserve">
<value>Edit ship call</value>
</data>
<data name="textEditTimes" xml:space="preserve">
<value>Edit times</value>
</data>
<data name="textEnterKeyword" xml:space="preserve">
<value>Enter keyword</value>
</data>
<data name="textETABerth" xml:space="preserve">
<value>ETA berth</value>
</data>
<data name="textETDBerth" xml:space="preserve">
<value>ETD berth</value>
</data>
<data name="textExit" xml:space="preserve">
<value>Exit</value>
</data>
<data name="textFixed" xml:space="preserve">
<value>Fixed</value>
</data>
<data name="textFrom" xml:space="preserve">
<value>from</value>
</data>
<data name="textInterval" xml:space="preserve">
<value>Interval</value>
</data>
<data name="textLengthWidth" xml:space="preserve">
<value>L/W</value>
</data>
<data name="textLockTime" xml:space="preserve">
<value>Lock time</value>
</data>
<data name="textLogin" xml:space="preserve">
<value>Login</value>
</data>
<data name="textMooredLock" xml:space="preserve">
<value>Moored in lock</value>
</data>
<data name="textMooring" xml:space="preserve">
<value>Mooring</value>
</data>
<data name="textNewDots" xml:space="preserve">
<value>New..</value>
</data>
<data name="textNewPassword" xml:space="preserve">
<value>New password</value>
</data>
<data name="textNotRotated" xml:space="preserve">
<value>Not rotated</value>
</data>
<data name="textOK" xml:space="preserve">
<value>OK</value>
</data>
<data name="textOldPassword" xml:space="preserve">
<value>Old password</value>
</data>
<data name="textOperationsEnd" xml:space="preserve">
<value>Operations end</value>
</data>
<data name="textOperationsStart" xml:space="preserve">
<value>Operations start</value>
</data>
<data name="textParticipants" xml:space="preserve">
<value>Participants</value>
</data>
<data name="textPassword" xml:space="preserve">
<value>Password</value>
</data>
<data name="textPierside" xml:space="preserve">
<value>Pier side</value>
</data>
<data name="textPilot" xml:space="preserve">
<value>Pilot</value>
</data>
<data name="textPilotRequired" xml:space="preserve">
<value>Pilot required</value>
</data>
<data name="textRainSensitiveCargo" xml:space="preserve">
<value>Rain sensitive cargo</value>
</data>
<data name="textRecommendedTugs" xml:space="preserve">
<value>Recommended tugs</value>
</data>
<data name="textRemarks" xml:space="preserve">
<value>Remarks</value>
</data>
<data name="textRepeatNewPassword" xml:space="preserve">
<value>Repeat new password</value>
</data>
<data name="textReplenishingLock" xml:space="preserve">
<value>Replenishing lock</value>
</data>
<data name="textReplenishingTerminal" xml:space="preserve">
<value>Replenishing terminal</value>
</data>
<data name="textRotated" xml:space="preserve">
<value>Rotated</value>
</data>
<data name="textSearch" xml:space="preserve">
<value>Search</value>
</data>
<data name="textShip" xml:space="preserve">
<value>Ship</value>
</data>
<data name="textShipLength" xml:space="preserve">
<value>Ship length</value>
</data>
<data name="textSortOrder" xml:space="preserve">
<value>Sort order</value>
</data>
<data name="textTerminal" xml:space="preserve">
<value>Terminal</value>
</data>
<data name="textTidalWindow" xml:space="preserve">
<value>Tidal window</value>
</data>
<data name="textTo" xml:space="preserve">
<value>to</value>
</data>
<data name="textTug" xml:space="preserve">
<value>Tug</value>
</data>
<data name="textTugRequired" xml:space="preserve">
<value>Tug required</value>
</data>
<data name="textType" xml:space="preserve">
<value>Type</value>
</data>
<data name="textUserlogin" xml:space="preserve">
<value>User login</value>
</data>
<data name="textUsername" xml:space="preserve">
<value>User name</value>
</data>
<data name="textVoyage" xml:space="preserve">
<value>Voyage</value>
</data>
<data name="textZoneEntryTime" xml:space="preserve">
<value>Zone entry</value>
</data>
<data name="trafficlight_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_off" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_off.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_on" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_on.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_red.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_red_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_red_yellow.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="trafficlight_yellow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>trafficlight_yellow.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="umbrella_closed" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>umbrella_closed.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="umbrella_open" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>umbrella_open.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="worker2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>worker2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -0,0 +1,10 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="textLoginCaption">Benutzer Anmeldung</system:String>
<system:String x:Key="textUsername">Benutzername</system:String>
<system:String x:Key="textPassword">Passwort</system:String>
<system:String x:Key="textLogin">Anmelden</system:String>
<system:String x:Key="textExit">Abbrechen</system:String>
<system:String x:Key="textUserNamePasswordEmpty">Benutzername / Password leer!</system:String>
</ResourceDictionary>

View File

@ -0,0 +1,11 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="textLoginCaption">User login</system:String>
<system:String x:Key="textUsername">Username</system:String>
<system:String x:Key="textPassword">Password</system:String>
<system:String x:Key="textLogin">Login</system:String>
<system:String x:Key="textExit">Exit</system:String>
<system:String x:Key="textApplicationTitle">Bremen calling</system:String>
<system:String x:Key="textUserNamePasswordEmpty">Username and/or password empty!</system:String>
</ResourceDictionary>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,81 @@
<UserControl x:Class="BreCalClient.SearchFilterControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p = "clr-namespace:BreCalClient.Resources"
xmlns:local="clr-namespace:BreCalClient"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
d:DesignHeight="56" d:DesignWidth="800" Loaded="UserControl_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".2*" />
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".2*" />
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".2*" />
</Grid.ColumnDefinitions>
<!-- Logo -->
<Image Grid.Column="0" Grid.RowSpan="2" x:Name="logoImage" Source="Resources/logo_bremen_calling.png" Stretch="Fill" MouseUp="logoImage_MouseUp" Margin="0"/>
<!-- Labels -->
<Label Grid.Row="0" Grid.Column="1" HorizontalContentAlignment="Right">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Source="{x:Static p:Resources.textInterval}" />
<Binding Source="{x:Static p:Resources.textFrom}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Label>
<Label Grid.Row="0" Grid.Column="3" Content="{x:Static p:Resources.textCategories}" HorizontalContentAlignment="Right" />
<Label Grid.Row="0" Grid.Column="5" HorizontalContentAlignment="Right">
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Source="{x:Static p:Resources.textShipLength}" />
<Binding Source="{x:Static p:Resources.textFrom}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Label>
<Label Grid.Row="1" Grid.Column="1" Content="{x:Static p:Resources.textSearch}" HorizontalContentAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="3" Content="{x:Static p:Resources.textBerths}" HorizontalContentAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="5" Content="{x:Static p:Resources.textAgencies}" HorizontalContentAlignment="Right"/>
<!-- Filter input controls -->
<Grid Grid.Column="2" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<DatePicker x:Name="datePickerETAFrom" Grid.Column="0" Margin="2" />
<Label Grid.Column="1" Content="{x:Static p:Resources.textTo}" />
<DatePicker x:Name="datePickerETATo" Grid.Column="2" Margin="2" />
</Grid>
<xctk:CheckComboBox x:Name="comboBoxCategories" Grid.Column="4" Margin="2" />
<Grid Grid.Column="6" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<xctk:DoubleUpDown x:Name="upDownShiplengthFrom" Grid.Column="0" Margin="2" Minimum="0" Maximum="1000" />
<Label Grid.Column="1" Content="{x:Static p:Resources.textTo}" />
<xctk:DoubleUpDown x:Name="upDownShiplengthTo" Grid.Column="2" Margin="2" Minimum="0" Maximum="1000"/>
</Grid>
<xctk:WatermarkTextBox x:Name="textBoxSearch" Grid.Column="2" Grid.Row="1" Margin="2" Watermark="{x:Static p:Resources.textEnterKeyword}" />
<xctk:CheckComboBox x:Name="comboBoxBerths" DisplayMemberPath="Name" Grid.Column="4" Grid.Row="1" Margin="2" />
<xctk:CheckComboBox x:Name="comboBoxAgencies" DisplayMemberPath="Name" Grid.Column="6" Grid.Row="1" Margin="2" />
</Grid>
</UserControl>

View File

@ -0,0 +1,68 @@
// Copyright (c) 2023 schick Informatik
// Description: Search filter bar for top window, generates events if filter criteria change
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Input;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for SearchFilterControl.xaml
/// </summary>
public partial class SearchFilterControl : UserControl
{
#region Construction
public SearchFilterControl()
{
InitializeComponent();
}
#endregion
#region events
public event Action? LogoImageClicked;
#endregion
#region Properties
#endregion
#region public methods
public void SetBerths(List<Berth> berths)
{
this.comboBoxBerths.ItemsSource = berths;
}
public void SetAgencies(List<Participant> agencies)
{
this.comboBoxAgencies.ItemsSource = agencies;
}
#endregion
#region event handler
private void logoImage_MouseUp(object sender, MouseButtonEventArgs e)
{
LogoImageClicked?.Invoke();
}
private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
this.comboBoxCategories.ItemsSource = Enum.GetValues(typeof(Extensions.TypeEnum));
}
#endregion
}
}

View File

@ -0,0 +1,36 @@
// Copyright (c) 2023 schick Informatik
// Description: Data model for search filters
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
namespace BreCalClient
{
internal class SearchFilterModel
{
public SearchFilterModel() { }
#region Properties
public DateTime? EtaFrom { get; set; }
public DateTime? EtaTo { get; set; }
public IEnumerable<int>? Categories { get; set; }
public IEnumerable<Participant>? Agencies { get; set; }
public IEnumerable<Berth>? Berths { get; set; }
public string? SearchString { get; set; }
public double? ShipLengthFrom { get; set; }
public double? ShipLengthTo { get; set; }
#endregion
}
}

View File

@ -0,0 +1,259 @@
<UserControl x:Class="BreCalClient.ShipcallControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BreCalClient"
xmlns:p = "clr-namespace:BreCalClient.Resources"
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalClient"
xmlns:db2="clr-namespace:BreCalClient.misc.Model;assembly=BreCalClient"
mc:Ignorable="d"
d:DesignHeight="120" d:DesignWidth="800" Loaded="UserControl_Loaded">
<Border BorderBrush="LightGray" Margin="1" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
<ColumnDefinition Width=".15*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" >
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height=".125*"/>
<RowDefinition Height=".125*"/>
<RowDefinition Height=".125*"/>
<RowDefinition Height=".05*"/>
<RowDefinition Height=".125*"/>
<RowDefinition Height=".125*"/>
<RowDefinition Height=".125*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".4*" />
<ColumnDefinition Width=".6*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" Grid.RowSpan="1" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Margin="2" Grid.Column="0" PreviewMouseUp="Image_PreviewMouseUp" x:Name="imageShipcallType" />
<Label Grid.Column="1" FontSize="12" x:Name="labelShipName" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" PreviewMouseUp="Image_PreviewMouseUp"/>
</Grid>
<Viewbox Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="IMO" />
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockIMO" Padding="0" FontWeight="DemiBold" />
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="{x:Static p:Resources.textCallsign}" />
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockCallsign" Padding="0"/>
</Viewbox>
<Viewbox Grid.Row="3" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="{x:Static p:Resources.textLengthWidth}" Padding="0" />
</Viewbox>
<Viewbox Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockLengthWidth" Padding="0"/>
</Viewbox>
<Viewbox Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="ETA" x:Name="labelETA"/>
</Viewbox>
<Viewbox Grid.Row="5" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockETA" />
</Viewbox>
<Viewbox Grid.Row="6" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="{x:Static p:Resources.textBerth}" />
</Viewbox>
<Viewbox Grid.Row="6" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockBerth" />
</Viewbox>
<Viewbox Grid.Row="7" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="{x:Static p:Resources.textAgency}" />
</Viewbox>
<Viewbox Grid.Row="7" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock x:Name="textBlockAgency" />
</Viewbox>
</Grid>
<Label Grid.Row="0" Grid.Column="1" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelAgent" PreviewMouseUp="labelAgent_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="2" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelMooring" PreviewMouseUp="labelMooring_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="3" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPortAuthority" PreviewMouseUp="labelPortAuthority_PreviewMouseUp" />
<Label Grid.Row="0" Grid.Column="4" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelPilot" PreviewMouseUp="labelPilot_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="5" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTug" PreviewMouseUp="labelTug_PreviewMouseUp"/>
<Label Grid.Row="0" Grid.Column="6" Grid.RowSpan="1" FontSize="12" Content="- / -" Foreground="White" Background="#203864" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Name="labelTerminal" PreviewMouseUp="labelTerminal_PreviewMouseUp" />
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelAgencyETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelAgencyETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockAgencyRemarks" />
</Grid>
<Grid Grid.Row="2" Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelMooringETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelMooringETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockMooringRemarks"/>
</Grid>
<Grid Grid.Row="2" Grid.Column="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPortAuthorityETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPortAuthorityETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockPortAuthorityRemarks"/>
</Grid>
<Grid Grid.Row="2" Grid.Column="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPilotETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelPilotETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockPilotRemarks"/>
</Grid>
<Grid Grid.Row="2" Grid.Column="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelTugETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelTugETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockTugRemarks" />
</Grid>
<Grid Grid.Row="2" Grid.Column="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="0.7*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="14" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="14" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textBerth}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="0" Content="ETA" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="2" Grid.Column="0" Content="ETD" Padding="0" VerticalContentAlignment="Center" />
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="{x:Static p:Resources.textRemarks}" Padding="0" VerticalContentAlignment="Center" FontSize="9"/>
<Label Grid.Row="1" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelTerminalETA" FontWeight="DemiBold"/>
<Label Grid.Row="2" Grid.Column="1" Padding="0" VerticalContentAlignment="Center" x:Name="labelTerminalETD" FontWeight="DemiBold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.RowSpan="2" Padding="0" TextWrapping="Wrap" VerticalAlignment="Top" x:Name="textBlockTerminalRemarks" />
</Grid>
<!-- Image Margin="2" Grid.Column="3" Grid.Row="0" Grid.RowSpan="3">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding NotFolderImage}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.OFF}">
<Setter Property="Source" Value="./Resources/trafficlight_off.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.RED}">
<Setter Property="Source" Value="./Resources/trafficlight_red.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.RED_YELLOW}">
<Setter Property="Source" Value="./Resources/trafficlight_red_yellow.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.GREEN}">
<Setter Property="Source" Value="./Resources/trafficlight_green.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.ALL}">
<Setter Property="Source" Value="./Resources/trafficlight_on.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding LightMode}" Value="{x:Static db:ShipcallControlModel+TrafficLightMode.YELLOW}">
<Setter Property="Source" Value="./Resources/trafficlight_yellow.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image-->
</Grid>
</Border>
</UserControl>

View File

@ -0,0 +1,276 @@
// Copyright (c) 2023 schick Informatik
// Description: Show general shipcall info
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for ShipcallControl.xaml
/// </summary>
public partial class ShipcallControl : UserControl
{
#region Construction
public ShipcallControl()
{
InitializeComponent();
}
#endregion
#region events
public event Action<ShipcallControl>? EditRequested;
public event Action<ShipcallControl, Times?>? EditTimesRequested;
public event Action<ShipcallControl>? OpenExtraRequested;
#endregion
#region Properties
/// <summary>
/// this is our datasource
/// </summary>
public ShipcallControlModel? ShipcallControlModel { get; set; }
/// <summary>
/// these are all participants (currently loaded)
/// </summary>
public Dictionary<int, Participant>? ParticipantDict { get; set; }
#endregion
#region public methods
public void RefreshData()
{
if (this.ShipcallControlModel == null) return;
string agentName = "";
string? name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.AGENCY);
if (name != null)
{
this.labelAgent.Content = name;
agentName = name;
}
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.MOORING);
if (name != null)
this.labelMooring.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.PILOT);
if (name != null)
this.labelPilot.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.TUG);
if (name != null)
this.labelTug.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.PORT_ADMINISTRATION);
if (name != null)
this.labelPortAuthority.Content = name;
name = this.ShipcallControlModel.GetParticipantNameForType(Extensions.ParticipantType.TERMINAL);
if (name != null)
this.labelTerminal.Content = name;
if(App.Participant.IsFlagSet(Extensions.ParticipantType.TERMINAL)) {
this.labelTerminal.FontWeight = FontWeights.Bold;
this.labelTerminal.Foreground = Brushes.LightYellow;
}
if(App.Participant.IsFlagSet(Extensions.ParticipantType.PILOT))
{
this.labelPilot.FontWeight = FontWeights.Bold;
this.labelPilot.Foreground = Brushes.LightYellow;
}
if(App.Participant.IsFlagSet(Extensions.ParticipantType.AGENCY))
{
this.labelAgent.FontWeight = FontWeights.Bold;
this.labelAgent.Foreground = Brushes.LightYellow;
}
if(App.Participant.IsFlagSet(Extensions.ParticipantType.MOORING))
{
this.labelMooring.FontWeight = FontWeights.Bold;
this.labelMooring.Foreground = Brushes.LightYellow;
}
if(App.Participant.IsFlagSet(Extensions.ParticipantType.PORT_ADMINISTRATION))
{
this.labelPortAuthority.FontWeight = FontWeights.Bold;
this.labelPortAuthority.Foreground = Brushes.LightYellow;
}
if (App.Participant.IsFlagSet(Extensions.ParticipantType.TUG))
{
this.labelTug.FontWeight = FontWeights.Bold;
this.labelTug.Foreground = Brushes.LightYellow;
}
this.labelShipName.Content = this.ShipcallControlModel?.Ship?.Name;
switch(this.ShipcallControlModel?.Shipcall?.Type)
{
case 1: // incoming
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_down_red.png"));
break;
case 2: // outgoing
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_up_green.png"));
break;
case 3: // shifting
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalClient;component/Resources/arrow_right_blue.png"));
break;
default:
break;
}
this.textBlockAgency.Text = this.ShipcallControlModel?.Agency;
this.textBlockBerth.Text = this.ShipcallControlModel?.Berth;
this.textBlockCallsign.Text = this.ShipcallControlModel?.Ship?.Callsign;
if ((this.ShipcallControlModel?.Shipcall?.Type == 1) || (this.ShipcallControlModel?.Shipcall?.Type == 3))
{
this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Eta.ToString("dd.MM. HH:mm");
}
if(this.ShipcallControlModel?.Shipcall?.Type == 2)
{
this.labelETA.Text = "ETD";
this.textBlockETA.Text = this.ShipcallControlModel?.Shipcall?.Etd?.ToString("dd.MM. HH:mm");
}
this.textBlockIMO.Text = this.ShipcallControlModel?.Ship?.Imo.ToString();
this.textBlockLengthWidth.Text = $"{this.ShipcallControlModel?.Ship?.Length} / {this.ShipcallControlModel?.Ship?.Width}";
this.textBlockAgency.Text = agentName.TruncateDots(10);
if (this.ParticipantDict != null)
{
if (this.ShipcallControlModel != null)
{
foreach (Times times in this.ShipcallControlModel.Times)
{
if(this.ParticipantDict.ContainsKey(times.ParticipantId))
{
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.AGENCY))
{
this.labelAgencyETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelAgencyETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockAgency.Text = times.Remarks;
}
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.MOORING))
{
this.labelMooringETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelMooringETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockMooringRemarks.Text = times.Remarks;
}
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.PORT_ADMINISTRATION))
{
this.labelPortAuthorityETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelPortAuthorityETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockPortAuthorityRemarks.Text = times.Remarks;
}
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.PILOT))
{
this.labelPilotETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelPilotETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockPilotRemarks.Text = times.Remarks;
}
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.TUG))
{
this.labelTugETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelTugETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockTugRemarks.Text = times.Remarks;
}
if (this.ParticipantDict[times.ParticipantId].IsFlagSet(Extensions.ParticipantType.TERMINAL))
{
this.labelTerminalETA.Content = times.EtaBerth.HasValue ? times.EtaBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.labelTerminalETD.Content = times.EtdBerth.HasValue ? times.EtdBerth.Value.ToString("dd.MM.yyyy HH:mm") : "- / -";
this.textBlockTerminalRemarks.Text = times.Remarks;
}
}
}
}
}
}
#endregion
#region event handler
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
}
private void buttonEditShipcall_Click(object sender, RoutedEventArgs e)
{
this.EditRequested?.Invoke(this);
}
private void buttonOpenDropDown_Click(object sender, RoutedEventArgs e)
{
this.OpenExtraRequested?.Invoke(this);
}
private void Image_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.EditRequested?.Invoke(this);
}
private void labelAgent_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.AGENCY))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.AGENCY);
this.EditTimesRequested?.Invoke(this, times);
}
}
private void labelMooring_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.MOORING))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.MOORING);
this.EditTimesRequested?.Invoke(this, times);
}
}
private void labelPortAuthority_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.PORT_ADMINISTRATION))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PORT_ADMINISTRATION);
this.EditTimesRequested?.Invoke(this, times);
}
}
private void labelPilot_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.PILOT))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.PILOT);
this.EditTimesRequested?.Invoke(this, times);
}
}
private void labelTug_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.TUG))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.TUG);
this.EditTimesRequested?.Invoke(this, times);
}
}
private void labelTerminal_PreviewMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (App.Participant.IsFlagSet(Extensions.ParticipantType.TERMINAL))
{
Times? times = this.ShipcallControlModel?.GetTimesForParticipantType(Extensions.ParticipantType.TERMINAL);
this.EditTimesRequested?.Invoke(this, times);
}
}
#endregion
}
}

View File

@ -0,0 +1,136 @@
// Copyright (c) 2023 schick Informatik
// Description: Container model for shipcall related info
//
using BreCalClient.misc.Model;
using System;
using System.Collections.Generic;
namespace BreCalClient
{
/// <summary>
/// Container model to aggregate separate models for the Shipcall control data binding
/// </summary>
public class ShipcallControlModel
{
#region Enumerations
public enum TrafficLightMode
{
OFF,
GREEN,
YELLOW,
RED,
RED_YELLOW,
ALL
};
[Flags]
public enum StatusFlags
{
RED,
GREEN,
YELLOW,
BLINK_1,
BLINK_2
};
#endregion
#region Properties
public Shipcall? Shipcall { get; set; }
public Ship? Ship { get; set; }
public string? Agency { get; set; }
public string? Berth { get; set; }
public Dictionary<int, Participant> AssignedParticipants { get; } = new();
public List<Times> Times { get; set; } = new();
public TrafficLightMode LightMode
{
get
{
if (IsFlagSet(StatusFlags.RED))
{
if (IsFlagSet((StatusFlags)StatusFlags.YELLOW))
{
if (IsFlagSet(StatusFlags.GREEN))
{
return TrafficLightMode.ALL;
}
return TrafficLightMode.RED_YELLOW;
}
return TrafficLightMode.RED;
}
if (IsFlagSet(StatusFlags.YELLOW))
return TrafficLightMode.YELLOW;
if (IsFlagSet(StatusFlags.GREEN))
return TrafficLightMode.GREEN;
return TrafficLightMode.OFF;
}
}
#endregion
#region public methods
public void AssignParticipants(List<Participant> participants)
{
this.AssignedParticipants.Clear();
if (Shipcall != null)
{
foreach (int participantId in Shipcall.Participants)
{
foreach(Participant participant in participants)
{
if(participant.Id == participantId)
AssignedParticipants[participant.Type] = participant;
}
}
}
}
internal Times? GetTimesForParticipantType(Extensions.ParticipantType type)
{
if (AssignedParticipants.ContainsKey((int)type)) {
int participantId = AssignedParticipants[(int)type].Id;
foreach (Times times in this.Times)
{
if (times.ParticipantId == participantId)
return times;
}
}
return null;
}
#endregion
#region helper
internal string? GetParticipantNameForType(Extensions.ParticipantType participantType)
{
foreach(Participant p in AssignedParticipants.Values)
{
if (p.IsFlagSet(participantType))
return p.Name;
}
return null;
}
private bool IsFlagSet(StatusFlags flag)
{
if(this.Shipcall == null) return false;
return (this.Shipcall.Flags & (int) flag) != 0;
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
<UserControl x:Class="BreCalClient.ShipcallExtraControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BreCalClient"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="800">
<Grid>
<Button x:Name="buttonCloseDropDown" Click="buttonCloseDropDown_Click" Grid.Column="2" Background="Transparent" ToolTip="Close extra info" Margin="1" BorderThickness="0" HorizontalAlignment="Left">
<Image Source="./Resources/arrow_up_red.png" />
</Button>
</Grid>
</UserControl>

View File

@ -0,0 +1,55 @@
// Copyright (c) 2023 schick Informatik
// Description: Extra shipcall info shown in drop down
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BreCalClient
{
/// <summary>
/// Interaction logic for ShipcallExtraControl.xaml
/// </summary>
public partial class ShipcallExtraControl : UserControl
{
public ShipcallExtraControl()
{
InitializeComponent();
}
#region events
public event Action<ShipcallExtraControl>? CloseExtraRequested;
#endregion
#region Properties
/// <summary>
/// this is our datasource
/// </summary>
public ShipcallControlModel? ShipcallControlModel { get; set; }
#endregion
private void buttonCloseDropDown_Click(object sender, RoutedEventArgs e)
{
if (this.CloseExtraRequested != null)
{
this.CloseExtraRequested(this);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -0,0 +1,4 @@
[*.cs]
# Default severity for all analyzer diagnostics
dotnet_analyzer_diagnostic.severity = none

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

9
src/RoleEditor/App.xaml Normal file
View File

@ -0,0 +1,9 @@
<Application x:Class="RoleEditor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RoleEditor"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace RoleEditor
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@ -0,0 +1,288 @@
// Copyright (c) 2017 schick Informatik
// Description: DataGrid mit etwas "verbesserten" Funktionen
//
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Controls.Primitives;
using System.Collections.Generic;
using brecal.model;
using System.Globalization;
using System.Threading;
namespace RoleEditor
{
/// <summary>
/// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
///
/// Step 1a) Using this custom control in a XAML file that exists in the current project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:enictrl="clr-namespace:ENI2.Controls"
///
///
/// Step 1b) Using this custom control in a XAML file that exists in a different project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:enictrl="clr-namespace:ENI2.Controls;assembly=ENI2.Controls"
///
/// You will also need to add a project reference from the project where the XAML file lives
/// to this project and Rebuild to avoid compilation errors:
///
/// Right click on the target project in the Solution Explorer and
/// "Add Reference"->"Projects"->[Browse to and select this project]
///
///
/// Step 2)
/// Go ahead and use your control in the XAML file.
///
/// <MyNamespace:ENIDataGrid/>
///
/// </summary>
public class ENIDataGrid : DataGrid
{
/*
static ENIDataGrid()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ENIDataGrid), new FrameworkPropertyMetadata(typeof(ENIDataGrid)));
}
*/
// das hier bildet 1:1 das Kontext-Menü des ANSW ab
public event Action<DbEntity>? EditRequested;
public event Action<DbEntity>? DeleteRequested;
public event Action? CreateRequested;
public event Action? RefreshGrid;
public event Action<DbEntity>? PrintRequested;
public event Action<DbEntity>? ExportRequested;
public event Action<DbEntity>? ShowTextRequested;
public void Initialize()
{
this.MouseDoubleClick += dataGrid_MouseDoubleClick;
this.PreviewKeyDown += ENIDataGrid_PreviewKeyDown;
this.ContextMenu = new ContextMenu();
this.CanUserAddRows = false;
this.IsReadOnly = false;
MenuItem addItem = new MenuItem();
addItem.Header = RoleEditor.Resources.ResourceManager.GetString("textAdd");
addItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.add) };
addItem.Click += new RoutedEventHandler(this.addItem);
this.ContextMenu.Items.Add(addItem);
MenuItem deleteItem = new MenuItem();
deleteItem.Header = RoleEditor.Resources.ResourceManager.GetString("textDelete");
deleteItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.delete) };
deleteItem.Click += this.deleteItem;
this.ContextMenu.Items.Add(deleteItem);
MenuItem editItem = new MenuItem();
editItem.Header = RoleEditor.Resources.ResourceManager.GetString("textEdit");
editItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.edit) };
editItem.Click += this.editItem;
this.ContextMenu.Items.Add(editItem);
/*
this.ContextMenu.Items.Add(new Separator());
MenuItem printItem = new MenuItem();
printItem.Header = RoleEditor.Resources.ResourceManager.GetString("textPrint");
printItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.printer) };
printItem.Click += this.printItem;
this.ContextMenu.Items.Add(printItem);
MenuItem exportItem = new MenuItem();
exportItem.Header = RoleEditor.Resources.ResourceManager.GetString("textExport");
exportItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.floppy_disk_blue) };
exportItem.Click += this.exportItem;
this.ContextMenu.Items.Add(exportItem);
MenuItem showTextItem = new MenuItem();
showTextItem.Header = RoleEditor.Resources.ResourceManager.GetString("textShowAsText");
showTextItem.Icon = new Image { Source = Util.LoadImage(RoleEditor.Resources.document_plain) };
showTextItem.Click += this.showTextItem;
this.ContextMenu.Items.Add(showTextItem);
*/
}
private void ENIDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(sender is ENIDataGrid)
{
var grid = sender as ENIDataGrid;
if (Key.Delete == e.Key)
this.deleteItem(null, null);
}
}
#region public
public DataGridRow GetRow(int index)
{
DataGridRow row = (DataGridRow)this.ItemContainerGenerator.ContainerFromIndex(index);
if(row == null)
{
this.UpdateLayout();
this.ScrollIntoView(this.Items[index]);
row = (DataGridRow)this.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
public DataGridCell? GetCell(DataGridRow row, int column)
{
if (row != null)
{
DataGridCellsPresenter? presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter == null)
{
this.ScrollIntoView(row, this.Columns[column]);
presenter = GetVisualChild<DataGridCellsPresenter>(row);
}
DataGridCell? cell = (DataGridCell?)presenter?.ItemContainerGenerator.ContainerFromIndex(column);
return cell;
}
return null;
}
public DataGridCell? GetCell(int rowIndex, int columnIndex)
{
DataGridRow row = this.GetRow(rowIndex);
return this.GetCell(row, columnIndex);
}
#endregion
#region protected
protected void addItem(object sender, RoutedEventArgs e)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
if (!this.IsReadOnly)
{
this.CreateRequested?.Invoke();
}
e.Handled = true;
}
protected void deleteItem(object? sender, RoutedEventArgs? e)
{
if((this.SelectedItems != null) && (this.SelectedItems.Count > 0) && !this.IsReadOnly)
{
MessageBoxResult result = MessageBox.Show("Are your sure?", "Please confirm", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
List<DbEntity> deleteList = new List<DbEntity>();
foreach (DbEntity deleteItem in this.SelectedItems)
deleteList.Add(deleteItem);
foreach (DbEntity deleteItem in deleteList)
{
if (deleteItem != null)
{
this.DeleteRequested?.Invoke(deleteItem);
}
}
this.RefreshGrid?.Invoke();
}
}
}
protected void editItem(object sender, RoutedEventArgs e)
{
if((this.SelectedItems != null) && (this.SelectedItems.Count == 1) && !this.IsReadOnly)
{
if (this.SelectedItems[0] is DbEntity selectedEntity)
this.EditRequested?.Invoke(selectedEntity);
}
}
protected void printItem(object sender, RoutedEventArgs e)
{
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1) )
{
if (this.SelectedItems[0] is DbEntity selectedEntity)
this.PrintRequested?.Invoke(selectedEntity);
}
}
protected void exportItem(object sender, RoutedEventArgs e)
{
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1))
{
if (this.SelectedItems[0] is DbEntity selectedEntity)
this.ExportRequested?.Invoke(selectedEntity);
}
}
protected void showTextItem(object sender, RoutedEventArgs e)
{
if ((this.SelectedItems != null) && (this.SelectedItems.Count == 1))
{
if (this.SelectedItems[0] is DbEntity selectedEntity)
this.ShowTextRequested?.Invoke(selectedEntity);
}
}
#endregion
#region private
private void dataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (sender != null)
{
if ((sender is DataGrid grid) && (grid.SelectedItems != null) && (grid.SelectedItems.Count == 1) && !this.IsReadOnly)
{
DataGridRow? dgr = grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem) as DataGridRow;
if (grid.SelectedItem is DbEntity selectedEntity)
this.EditRequested?.Invoke(selectedEntity);
}
}
}
#endregion
#region private static
private static T? GetVisualChild<T>(Visual parent) where T : Visual
{
T? child = default;
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual? v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
#endregion
}
}

View File

@ -0,0 +1,41 @@
<Window x:Class="RoleEditor.EditBerthDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RoleEditor"
mc:Ignorable="d"
Title="Edit berth" Height="160" Width="450" Loaded="Window_Loaded">
<Grid x:Name="berthGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".3*" />
<ColumnDefinition Width=".6*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Label Content="Name" HorizontalAlignment="Right" />
<TextBox x:Name="textBoxName" Grid.Column="1" Margin="2" VerticalContentAlignment="Center" Text="{Binding Name, Mode=OneWay}" />
<Label Content="Participant / Terminal" HorizontalAlignment="Right" Grid.Row="1" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="28" />
</Grid.ColumnDefinitions>
<ComboBox x:Name="comboBoxParticipants" Margin="2" SelectedItem="{Binding Participant, Mode=OneWay}" />
<Button x:Name="buttonResetParticipant" Grid.Column="1" Margin="2" Click="buttonResetParticipant_Click">
<Image Source="./Resources/delete2.png"/>
</Button>
</Grid>
<Label Content="Uses lock" HorizontalAlignment="Right" Grid.Row="2" />
<CheckBox x:Name="checkBoxLock" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="2" IsChecked="{Binding Path=Lock, Mode=OneWay}"/>
<StackPanel Grid.Column="1" Grid.Row="4" Orientation="Horizontal" FlowDirection="RightToLeft">
<Button x:Name="buttonCancel" Width="80" Content="Cancel" Margin="2" Click="buttonCancel_Click" />
<Button x:Name="buttonOK" Width="80" Content="OK" Margin="2" Click="buttonOK_Click"/>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,51 @@
using brecal.model;
using System.Collections.Generic;
using System.Windows;
namespace RoleEditor
{
/// <summary>
/// Interaction logic for EditBerthDialog.xaml
/// </summary>
public partial class EditBerthDialog : Window
{
public EditBerthDialog()
{
InitializeComponent();
}
public Berth Berth { get; set; } = new Berth();
public List<Participant> Participants { get; } = new List<Participant>();
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
private void buttonOK_Click(object sender, RoutedEventArgs e)
{
this.Berth.Name = this.textBoxName.Text.Trim();
this.Berth.Lock = this.checkBoxLock.IsChecked;
this.Berth.Participant = this.comboBoxParticipants.SelectedItem as Participant;
if (this.Berth.Participant != null)
this.Berth.Participant_Id = this.Berth.Participant.Id;
else
this.Berth.Participant_Id = null;
this.DialogResult = true;
this.Close();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this.Berth;
this.comboBoxParticipants.ItemsSource = this.Participants;
}
private void buttonResetParticipant_Click(object sender, RoutedEventArgs e)
{
this.comboBoxParticipants.SelectedItem = null;
}
}
}

View File

@ -0,0 +1,52 @@
<Window x:Class="RoleEditor.EditShipDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RoleEditor"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="Edit ship" Height="250" Width="500" Loaded="Window_Loaded">
<Grid x:Name="shipGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".3*" />
<ColumnDefinition Width=".6*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Label Content="Name" HorizontalAlignment="Right" />
<TextBox x:Name="textBoxName" Grid.Column="1" Margin="2" VerticalContentAlignment="Center" Text="{Binding Name, Mode=OneWay}" />
<Label Content="Participant / Tug company" HorizontalAlignment="Right" Grid.Row="1" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="28" />
</Grid.ColumnDefinitions>
<ComboBox x:Name="comboBoxParticipants" Margin="2" SelectedItem="{Binding Participant, Mode=OneWay}" />
<Button x:Name="buttonResetParticipant" Grid.Column="1" Margin="2" Click="buttonResetParticipant_Click">
<Image Source="./Resources/delete2.png"/>
</Button>
</Grid>
<Label Content="IMO" HorizontalAlignment="Right" Grid.Row="2" />
<xctk:IntegerUpDown Name="integerUpDownIMO" Grid.Column="1" Grid.Row="2" Value="{Binding IMO, Mode=OneWay}" Margin="2" Minimum="1000000" Maximum="9999999"/>
<Label Content="Callsign" HorizontalAlignment="Right" Grid.Row="3" />
<TextBox x:Name="textBoxCallsign" Grid.Column="1" Grid.Row="3" Margin="2" VerticalContentAlignment="Center" Text="{Binding Callsign, Mode=OneWay}" />
<Label Content="Length" HorizontalAlignment="Right" Grid.Row="4" />
<xctk:DoubleUpDown Name="doubleUpDownLength" Grid.Row="4" Grid.Column="1" Value="{Binding Length, Mode=OneWay}" Margin="2" Minimum="0" />
<Label Content="Width" HorizontalAlignment="Right" Grid.Row="5" />
<xctk:DoubleUpDown Name="doubleUpDownWidth" Grid.Row="5" Grid.Column="1" Value="{Binding Width, Mode=OneWay}" Margin="2" Minimum="0"/>
<StackPanel Grid.Column="1" Grid.Row="7" Orientation="Horizontal" FlowDirection="RightToLeft">
<Button x:Name="buttonCancel" Width="80" Content="Cancel" Margin="2" Click="buttonCancel_Click" />
<Button x:Name="buttonOK" Width="80" Content="OK" Margin="2" Click="buttonOK_Click"/>
</StackPanel>
</Grid>
</Window>

View File

@ -0,0 +1,55 @@
using brecal.model;
using System.Collections.Generic;
using System.Windows;
namespace RoleEditor
{
/// <summary>
/// Interaction logic for EditShipDialog.xaml
/// </summary>
public partial class EditShipDialog : Window
{
public EditShipDialog()
{
InitializeComponent();
}
public Ship Ship { get; set; } = new Ship();
public List<Participant> Participants { get; } = new List<Participant>();
private void buttonCancel_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
private void buttonOK_Click(object sender, RoutedEventArgs e)
{
this.Ship.Name = this.textBoxName.Text.Trim();
this.Ship.Participant = this.comboBoxParticipants.SelectedItem as Participant;
if (this.Ship.Participant != null)
this.Ship.Participant_Id = this.Ship.Participant.Id;
else
this.Ship.Participant_Id = null;
this.Ship.IMO = this.integerUpDownIMO.Value;
this.Ship.Callsign = this.textBoxCallsign.Text.Trim();
this.Ship.Length = this.doubleUpDownLength.Value;
this.Ship.Width = this.doubleUpDownWidth.Value;
this.DialogResult = true;
this.Close();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this.Ship;
this.comboBoxParticipants.ItemsSource = this.Participants;
}
private void buttonResetParticipant_Click(object sender, RoutedEventArgs e)
{
this.comboBoxParticipants.SelectedItem = null;
}
}
}

View File

@ -0,0 +1,288 @@
<Window x:Class="RoleEditor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RoleEditor"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="Bremen calling admin editor" Height="650" Width="800" Icon="Resources/lock_preferences.ico" Loaded="Window_Loaded">
<Grid>
<TabControl>
<TabItem Header="Participant, users and roles">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=".5*" />
<RowDefinition Height=".5*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<GroupBox Header="Participant" Margin="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".4*" />
<ColumnDefinition Width=".2*" />
<ColumnDefinition Width=".4*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="listBoxParticipant" Margin="2" Grid.RowSpan="7" SelectionChanged="listBoxParticipant_SelectionChanged">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuItemNewParticipant" Header="New.." Click="menuItemNewParticipant_Click">
<MenuItem.Icon>
<Image Source="Resources/add.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemDeleteParticipant" Header="Delete" Click="menuItemDeleteParticipant_Click">
<MenuItem.Icon>
<Image Source="Resources/delete2.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Label Content="Name" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Street" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Postal code" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="City" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Active" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Type" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Created" Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Modified" Grid.Row="7" Grid.Column="1" HorizontalAlignment="Right"/>
<TextBox x:Name="textBoxParticipantName" Grid.Row="0" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxParticipantStreet" Grid.Row="1" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxParticipantPostalCode" Grid.Row="2" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxParticipantCity" Grid.Row="3" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<CheckBox x:Name="checkboxParticipantActive" Grid.Row="4" Grid.Column="2" VerticalAlignment="Center" />
<xctk:CheckComboBox x:Name="comboBoxParticipantType" Grid.Row="5" Grid.Column="2" Margin="2" SelectedValue="Key" DisplayMemberPath="Value" />
<TextBox x:Name="textBoxParticipantCreated" Grid.Row="6" IsReadOnly="True" IsEnabled="False" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxParticipantModified" Grid.Row="7" IsReadOnly="True" IsEnabled="False" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<Button x:Name="buttonParticipantSave" Grid.Row="8" Grid.Column="2" Click="buttonParticipantSave_Click" Margin="2">
<DockPanel>
<Image Source="./Resources/disk_blue.png" Margin="0,0,5,0" Height="24" DockPanel.Dock="Left" Width="16"/>
<TextBlock Text="Save" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Button>
</Grid>
</GroupBox>
<GroupBox Header="User" Margin="2" Grid.Row="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width=".38*" />
<ColumnDefinition Width=".62*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="listBoxUser" Margin="2" Grid.RowSpan="9" SelectionChanged="listBoxUser_SelectionChanged">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuItemNewUser" Header="New.." Click="menuItemNewUser_Click">
<MenuItem.Icon>
<Image Source="Resources/add.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemDeleteUser" Header="Delete" Click="menuItemDeleteUser_Click">
<MenuItem.Icon>
<Image Source="Resources/delete2.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Label Grid.Row="0" Grid.Column="1" Content="First name" HorizontalAlignment="Right"/>
<Label Grid.Row="1" Grid.Column="1" Content="Last name" HorizontalAlignment="Right"/>
<Label Grid.Row="2" Grid.Column="1" Content="User name" HorizontalAlignment="Right"/>
<Label Grid.Row="3" Grid.Column="1" Content="Password" HorizontalAlignment="Right"/>
<Label Grid.Row="4" Grid.Column="1" Content="API Key" HorizontalAlignment="Right"/>
<Label Content="Created" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right"/>
<Label Content="Modified" Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right"/>
<TextBox x:Name="textBoxUserFirstName" Grid.Row="0" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserLastName" Grid.Row="1" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserUserName" Grid.Row="2" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserPassword" Grid.Row="3" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserAPIKey" Grid.Row="4" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserCreated" Grid.Row="5" IsReadOnly="True" IsEnabled="False" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<TextBox x:Name="textBoxUserModified" Grid.Row="6" IsReadOnly="True" IsEnabled="False" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
<Button x:Name="buttonUserSave" Grid.Row="7" Grid.Column="2" Click="buttonUserSave_Click" Margin="2">
<DockPanel>
<Image Source="./Resources/disk_blue.png" Margin="0,0,5,0" Height="24" DockPanel.Dock="Left" Width="16"/>
<TextBlock Text="Save" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Button>
</Grid>
</GroupBox>
<GroupBox Header="Role" Margin="2" Grid.Column="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Label Content="User roles" Grid.Row="0" Grid.Column="0" />
<Label Content="All roles" Grid.Row="0" Grid.Column="2" />
<ListBox x:Name="listBoxUserRoles" Grid.Row="1" Grid.Column="0" Grid.RowSpan="3" Margin="2" />
<ListBox x:Name="listBoxRoles" Grid.Row="1" Grid.Column="2" Grid.RowSpan="3" Margin="2" SelectionChanged="listBoxRoles_SelectionChanged">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuItemNewRole" Header="New.." Click="menuItemNewRole_Click">
<MenuItem.Icon>
<Image Source="Resources/add.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemDeleteRole" Header="Delete" Click="menuItemDeleteRole_Click">
<MenuItem.Icon>
<Image Source="Resources/delete2.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Button x:Name="buttonAddRole" Margin="2" Grid.Row="1" Grid.Column="1" Click="buttonAddRole_Click">
<Image Source="./Resources/arrow_left_green.png"/>
</Button>
<Button x:Name="buttonRemoveRole" Margin="2" Grid.Row="2" Grid.Column="1" Click="buttonRemoveRole_Click">
<Image Source="./Resources/delete2.png"/>
</Button>
<Label Content="Name" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" />
<Label Content="Descr." Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right" />
<TextBox x:Name="textBoxRoleName" Grid.Row="4" Grid.Column="2" Margin="2" VerticalContentAlignment="Center"/>
<TextBox x:Name="textBoxRoleDescription" Grid.Row="5" Grid.Column="2" Grid.RowSpan="2" Margin="2" VerticalContentAlignment="Top"/>
<Button x:Name="buttonSaveRole" Grid.Row="7" Grid.Column="2" Margin="2" Click="buttonSaveRole_Click">
<DockPanel>
<Image Source="./Resources/disk_blue.png" Margin="0,0,5,0" Height="24" DockPanel.Dock="Left" Width="16"/>
<TextBlock Text="Save" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Button>
</Grid>
</GroupBox>
<GroupBox Header="Securable" Margin="2" Grid.Row="1" Grid.Column="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="*"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Role securables" />
<Label Grid.Row="0" Grid.Column="2" Content="Securables" />
<ListBox x:Name="listBoxRoleSecurables" Grid.Row="1" Grid.Column="0" Grid.RowSpan="3" Margin="2" />
<ListBox x:Name="listBoxSecurables" Grid.Row="1" Grid.Column="2" Grid.RowSpan="3" Margin="2" SelectionChanged="listBoxSecurables_SelectionChanged">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="menuItemNewSecurable" Header="New.." Click="menuItemNewSecurable_Click">
<MenuItem.Icon>
<Image Source="Resources/add.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="menuItemDeleteSecurable" Header="Delete" Click="menuItemDeleteSecurable_Click">
<MenuItem.Icon>
<Image Source="Resources/delete2.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Button x:Name="buttonAddSecurable" Margin="2" Grid.Row="1" Grid.Column="1" Click="buttonAddSecurable_Click">
<Image Source="./Resources/arrow_left_green.png"/>
</Button>
<Button x:Name="buttonRemoveSecurable" Margin="2" Grid.Row="2" Grid.Column="1" Click="buttonRemoveSecurable_Click">
<Image Source="./Resources/delete2.png"/>
</Button>
<Label Content="Name" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" />
<TextBox x:Name="textBoxSecurableName" Grid.Row="4" Grid.Column="2" Margin="2" VerticalContentAlignment="Center"/>
<Button x:Name="buttonSaveSecurable" Grid.Row="5" Grid.Column="2" Margin="2" Click="buttonSaveSecurable_Click">
<DockPanel>
<Image Source="./Resources/disk_blue.png" Margin="0,0,5,0" Height="24" DockPanel.Dock="Left" Width="16"/>
<TextBlock Text="Save" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</Button>
</Grid>
</GroupBox>
</Grid>
</TabItem>
<TabItem Header="Berths">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Content="Import excel" Margin="2" x:Name="buttonImportBerths" Click="buttonImportBerths_Click" Width="100" HorizontalAlignment="Left" Grid.Row="0"/>
<local:ENIDataGrid x:Name="dataGridBerths" Grid.Row="1" SelectionMode="Single" IsReadOnly="True" AlternatingRowBackground="LightBlue" AutoGenerateColumns="False"
CanUserAddRows="False" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Path=Id}" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True"/>
<DataGridCheckBoxColumn Header="Lock" Binding="{Binding Path=Lock}" IsReadOnly="True"/>
<DataGridTextColumn Header="Terminal" Binding="{Binding Path=Terminal, Mode=OneWay}" IsReadOnly="True"/>
</DataGrid.Columns>
</local:ENIDataGrid>
</Grid>
</TabItem>
<TabItem Header="Ships">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Content="Import excel" Margin="2" x:Name="buttonImportShipss" Click="buttonImportShipss_Click" Width="100" HorizontalAlignment="Left" Grid.Row="0"/>
<local:ENIDataGrid x:Name="dataGridShips" Grid.Row="1" SelectionMode="Single" IsReadOnly="True" AlternatingRowBackground="LightBlue" AutoGenerateColumns="False"
CanUserAddRows="False" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Path=Id}" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True"/>
<DataGridCheckBoxColumn Header="Tug" Binding="{Binding Path=IsTug, Mode=OneWay}" IsReadOnly="True"/>
<DataGridTextColumn Header="Tug company" Binding="{Binding Path=TugCompany, Mode=OneWay}" IsReadOnly="True"/>
<DataGridTextColumn Header="IMO" Binding="{Binding Path=IMO}" IsReadOnly="True"/>
<DataGridTextColumn Header="Callsign" Binding="{Binding Path=Callsign}" IsReadOnly="True"/>
<DataGridTextColumn Header="Length" Binding="{Binding Path=Length}" IsReadOnly="True"/>
<DataGridTextColumn Header="Width" Binding="{Binding Path=Width}" IsReadOnly="True"/>
</DataGrid.Columns>
</local:ENIDataGrid>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>

View File

@ -0,0 +1,705 @@

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using brecal.model;
using brecal.mysql;
using ExcelDataReader;
using Microsoft.Win32;
namespace RoleEditor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region private fields
private readonly ObservableCollection<Participant> _participants = new ObservableCollection<Participant>();
private readonly ObservableCollection<Role> _roles = new ObservableCollection<Role>();
private readonly ObservableCollection<Securable> _securables = new ObservableCollection<Securable>();
private readonly ObservableCollection<User> _users = new ObservableCollection<User>();
private readonly ObservableCollection<RoleAssignment> _assignedRoles = new ObservableCollection<RoleAssignment>();
private readonly ObservableCollection<SecurableAssignment> _assignedSecurables = new ObservableCollection<SecurableAssignment>();
private readonly ObservableCollection<Berth> _berths = new ObservableCollection<Berth>();
private readonly ObservableCollection<Ship> _ships = new ObservableCollection<Ship>();
private DBManager _dbManager;
#endregion
#region Construction / Loading
public MainWindow()
{
InitializeComponent();
_dbManager = new();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); // for ExcelDataReader on .NET Core
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
// try database connection
try
{
// load all participants
List<Participant> participants = await Participant.LoadAll(_dbManager);
foreach(Participant p in participants)
_participants.Add(p);
this.listBoxParticipant.ItemsSource = _participants;
// load all roles
foreach(Role r in await Role.LoadAll(_dbManager))
_roles.Add(r);
this.listBoxRoles.ItemsSource = _roles;
// load all securables
foreach(Securable s in await Securable.LoadAll(_dbManager))
_securables.Add(s);
this.listBoxSecurables.ItemsSource = _securables;
// load all berths
foreach (Berth b in await Berth.LoadAll(_dbManager))
{
_berths.Add(b);
if(b.Participant_Id != null)
{
b.Participant = participants.Where( p => p.Id== b.Participant_Id ).FirstOrDefault();
}
}
this.dataGridBerths.Initialize();
this.dataGridBerths.ItemsSource = _berths;
this.dataGridBerths.CreateRequested += DataGridBerths_CreateRequested;
this.dataGridBerths.EditRequested += DataGridBerths_EditRequested;
this.dataGridBerths.DeleteRequested += DataGridBerths_DeleteRequested;
// load all ships
foreach (Ship s in await Ship.LoadAll(_dbManager))
{
_ships.Add(s);
if(s.Participant_Id != null)
{
s.Participant = participants.Where( p => p.Id == s.Participant_Id ).FirstOrDefault();
}
}
this.dataGridShips.Initialize();
this.dataGridShips.ItemsSource = _ships;
this.dataGridShips.CreateRequested += DataGridShips_CreateRequested;
this.dataGridShips.EditRequested += DataGridShips_EditRequested;
this.dataGridShips.DeleteRequested += DataGridShips_DeleteRequested;
// set other item sources (filled later after selection)
this.listBoxUser.ItemsSource = _users;
this.listBoxRoleSecurables.ItemsSource = _assignedSecurables;
this.listBoxUserRoles.ItemsSource = _assignedRoles;
this.comboBoxParticipantType.ItemsSource = EnumHelper.GetAllValuesAndDescription(typeof(Participant.ParticipantType));
}
catch (Exception ex)
{
MessageBox.Show($"Database connection couldn't be established: {ex.Message}");
this.Close();
}
}
#region ship context menu callbacks
private void DataGridShips_DeleteRequested(DbEntity obj)
{
if(obj is Ship s)
this._ships.Remove(s);
}
private async void DataGridShips_EditRequested(DbEntity obj)
{
if(obj is Ship s)
{
EditShipDialog esd = new();
esd.Ship = s;
esd.Participants.AddRange(this._participants);
if (esd.ShowDialog() ?? false)
{
await s.Save(_dbManager);
this.dataGridShips.ItemsSource = null;
this.dataGridShips.ItemsSource = _ships;
}
}
}
private async void DataGridShips_CreateRequested()
{
Ship s = new();
EditShipDialog esd = new();
esd.Ship = s;
esd.Participants.AddRange(this._participants);
if(esd.ShowDialog() ?? false)
{
_ships.Add(s);
await s.Save(_dbManager);
this.dataGridShips.ItemsSource = null;
this.dataGridShips.ItemsSource = _ships;
}
}
#endregion
#region berth context menu callbacks
private void DataGridBerths_DeleteRequested(DbEntity obj)
{
if(obj is Berth b)
this._berths.Remove(b);
}
private async void DataGridBerths_EditRequested(DbEntity obj)
{
if(obj is Berth b)
{
EditBerthDialog ebd = new();
ebd.Berth = b;
ebd.Participants.AddRange(this._participants);
if (ebd.ShowDialog() ?? false)
{
await b.Save(_dbManager);
this.dataGridBerths.ItemsSource = null; // extreme stupidity for me not wanting to implement INotifyPropertyChanged
this.dataGridBerths.ItemsSource = _berths;
}
}
}
private async void DataGridBerths_CreateRequested()
{
Berth b = new();
EditBerthDialog ebd = new();
ebd.Berth = b;
ebd.Participants.AddRange(this._participants);
if (ebd.ShowDialog() ?? false)
{
_berths.Add(b);
await b.Save(_dbManager);
this.dataGridBerths.ItemsSource = null;
this.dataGridBerths.ItemsSource = _berths;
}
}
#endregion
#endregion
#region button callbacks
private async void buttonParticipantSave_Click(object sender, RoutedEventArgs e)
{
Participant? p = this.listBoxParticipant.SelectedItem as Participant;
if (p != null)
{
p.Name = this.textBoxParticipantName.Text.Trim();
p.Street = this.textBoxParticipantStreet.Text.Trim();
p.PostalCode = this.textBoxParticipantPostalCode.Text.Trim();
p.City = this.textBoxParticipantCity.Text.Trim();
p.Type = 0;
for(int i = 0; i < this.comboBoxParticipantType?.SelectedItems.Count; i++)
{
object? v = this.comboBoxParticipantType?.SelectedItems[i];
if (v != null)
{
KeyValuePair<string, string> kvp = (KeyValuePair<string, string>)v;
Participant.ParticipantType pType = (Participant.ParticipantType)Enum.Parse(typeof(Participant.ParticipantType), kvp.Key);
p.SetFlag(true, pType);
}
}
await p.Save(_dbManager);
this.listBoxParticipant.ItemsSource = null;
this.listBoxParticipant.ItemsSource = _participants;
this.listBoxParticipant.SelectedItem = p;
}
}
private async void buttonUserSave_Click(object sender, RoutedEventArgs e)
{
User? u = this.listBoxUser.SelectedItem as User;
if(u != null)
{
u.Firstname = this.textBoxUserFirstName.Text.Trim();
u.Lastname = this.textBoxUserLastName.Text.Trim();
u.Username = this.textBoxUserUserName.Text.Trim();
if(this.textBoxUserPassword.Text.Trim().Length > 0 )
{
string passwortText = this.textBoxUserPassword.Text.Trim();
byte[] bytes = Encoding.Default.GetBytes(passwortText);
passwortText = Encoding.UTF8.GetString(bytes);
// Das sollte nicht verändert werden um kompatibel zu der Python Implementierung zu bleiben
string salt = BCrypt.Net.BCrypt.GenerateSalt(12, 'b');
u.PasswordHash = BCrypt.Net.BCrypt.HashPassword(passwortText, salt);
}
u.APIKey = this.textBoxUserAPIKey.Text.Trim();
await u.Save(_dbManager);
this.listBoxUser.ItemsSource = null;
this.listBoxUser.ItemsSource = _users;
this.listBoxUser.SelectedItem = u;
}
}
private async void buttonAddRole_Click(object sender, RoutedEventArgs e)
{
Role? r = this.listBoxRoles.SelectedItem as Role;
User? u = this.listBoxUser.SelectedItem as User;
if((r != null) && (u != null))
{
// test if assignment is already present
bool foundMatchingAssignment = false;
foreach(RoleAssignment ra in _assignedRoles)
{
if((ra.UserId == u.Id) && (ra.RoleId == r.Id))
{
foundMatchingAssignment = true;
break;
}
}
if(!foundMatchingAssignment)
{
RoleAssignment ra = new RoleAssignment();
ra.UserId = (int) u.Id;
ra.RoleId = (int) r.Id;
ra.AssignedRole = r;
ra.AssignedUser = u;
await ra.Save(_dbManager);
_assignedRoles.Add(ra);
}
}
}
private async void buttonRemoveRole_Click(object sender, RoutedEventArgs e)
{
// remove role from user
RoleAssignment? ra = this.listBoxUserRoles.SelectedItem as RoleAssignment;
if(ra != null)
{
await ra.Delete(_dbManager);
if(_assignedRoles.Contains(ra))
_assignedRoles.Remove(ra);
}
}
private async void buttonAddSecurable_Click(object sender, RoutedEventArgs e)
{
if ((this.listBoxRoles.SelectedItem is Role r) && (this.listBoxSecurables.SelectedItem is Securable s))
{
// test if assignment is already present
bool foundMatchingAssignment = false;
foreach (SecurableAssignment sa in _assignedSecurables)
{
if ((sa.SecurableId == s.Id) && (sa.RoleId == r.Id))
{
foundMatchingAssignment = true;
break;
}
}
if (!foundMatchingAssignment)
{
SecurableAssignment sa = new SecurableAssignment();
sa.SecurableId = (int)s.Id;
sa.RoleId = (int)r.Id;
sa.AssignedRole = r;
sa.AssignedSecurable = s;
await sa.Save(_dbManager);
_assignedSecurables.Add(sa);
}
}
}
private async void buttonRemoveSecurable_Click(object sender, RoutedEventArgs e)
{
SecurableAssignment? sa = this.listBoxRoleSecurables.SelectedItem as SecurableAssignment;
if(sa != null)
{
await sa.Delete(_dbManager);
if (_assignedSecurables.Contains(sa))
_assignedSecurables.Remove(sa);
}
}
private async void buttonSaveSecurable_Click(object sender, RoutedEventArgs e)
{
Securable? s = this.listBoxSecurables.SelectedItem as Securable;
if(s != null)
{
s.Name = this.textBoxSecurableName.Text.Trim();
await s.Save(_dbManager);
this.listBoxSecurables.ItemsSource = null;
this.listBoxSecurables.ItemsSource = _securables;
this.listBoxSecurables.SelectedItem = s;
}
}
private async void buttonSaveRole_Click(object sender, RoutedEventArgs e)
{
Role? r = this.listBoxRoles.SelectedItem as Role;
if(r != null)
{
r.Name = this.textBoxRoleName.Text.Trim();
r.Description = this.textBoxRoleDescription.Text.Trim();
await r.Save(_dbManager);
this.listBoxRoles.ItemsSource = null;
this.listBoxRoles.ItemsSource = _roles;
this.listBoxRoles.SelectedItem = r;
}
}
#endregion
#region listbox selection callbacks
private async void listBoxParticipant_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Participant? p = this.listBoxParticipant.SelectedItem as Participant;
this.textBoxParticipantName.Text = (p != null) ? p.Name : string.Empty;
this.textBoxParticipantStreet.Text = (p != null) ? p.Street : string.Empty;
this.textBoxParticipantPostalCode.Text = (p != null) ? p.PostalCode : string.Empty;
this.textBoxParticipantCity.Text = (p != null) ? p.City : string.Empty;
// this.checkboxParticipantActive.Checked = (p != null) ? p.
this.textBoxParticipantCreated.Text = (p != null) ? p.Created.ToString() : string.Empty;
this.textBoxParticipantModified.Text = (p != null) ? p.Modified.ToString() : string.Empty;
this.comboBoxParticipantType.SelectedItems.Clear();
if (p != null)
{
foreach (Participant.ParticipantType pType in Enum.GetValues(typeof(Participant.ParticipantType)))
{
if (p.IsFlagSet(pType))
{
foreach (KeyValuePair<string, string> kvp in this.comboBoxParticipantType.Items)
{
if (kvp.Key.Equals(pType.ToString()))
{
this.comboBoxParticipantType.SelectedItems.Add(kvp);
}
}
}
}
}
// -> load users for this participant selection
this._users.Clear();
if (p != null)
{
foreach (User u in await User.LoadForParticipant(p, _dbManager))
_users.Add(u);
}
}
private async void listBoxRoles_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Role? r = this.listBoxRoles.SelectedItem as Role;
this.textBoxRoleName.Text = (r != null) ? r.Name : string.Empty;
this.textBoxRoleDescription.Text = (r != null) ? r.Description : string.Empty;
_assignedSecurables.Clear();
if (r != null)
{
// load assigned securables
foreach (SecurableAssignment sa in await SecurableAssignment.LoadForRole(r, _dbManager))
{
foreach (Securable s in this._securables)
{
if (sa.SecurableId == s.Id)
{
sa.AssignedSecurable = s;
break;
}
}
_assignedSecurables.Add(sa);
}
}
}
private async void listBoxUser_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
User? u = this.listBoxUser.SelectedItem as User;
this.textBoxUserFirstName.Text = (u != null) ? u.Firstname : string.Empty;
this.textBoxUserLastName.Text = (u != null) ? u.Lastname : string.Empty;
this.textBoxUserUserName.Text = (u != null) ? u.Username : string.Empty;
this.textBoxUserAPIKey.Text = (u != null) ? u.APIKey : string.Empty;
this.textBoxUserCreated.Text = (u != null) ? u.Created.ToString() : string.Empty;
this.textBoxUserModified.Text = (u != null) ? u.Modified.ToString() : string.Empty;
this.textBoxUserPassword.Text = string.Empty;
_assignedRoles.Clear();
if (u != null)
{
// load roles assigned to user
foreach (RoleAssignment ra in await RoleAssignment.LoadForUser(u, _dbManager))
{
foreach (Role r in this._roles)
{
if (ra.RoleId == r.Id)
{
ra.AssignedRole = r;
break;
}
}
_assignedRoles.Add(ra);
}
}
}
private void listBoxSecurables_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Securable? s = this.listBoxSecurables.SelectedItem as Securable;
this.textBoxSecurableName.Text = (s != null) ? s.Name : string.Empty;
}
#endregion
#region menuitem callbacks
private async void menuItemDeleteParticipant_Click(object sender, RoutedEventArgs e)
{
try
{
if(this.listBoxParticipant.SelectedItem is Participant p)
{
await p.Delete(_dbManager);
this._participants.Remove(p);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void menuItemNewParticipant_Click(object sender, RoutedEventArgs e)
{
Participant p = new();
this._participants.Add(p);
this.listBoxParticipant.SelectedItem = p;
}
private void menuItemNewUser_Click(object sender, RoutedEventArgs e)
{
Participant? p = this.listBoxParticipant.SelectedItem as Participant;
if(p != null)
{
User u = new();
u.Participant_Id = p.Id;
_users.Add(u);
this.listBoxUser.SelectedItem = u;
}
}
private async void menuItemDeleteUser_Click(object sender, RoutedEventArgs e)
{
try
{
if (this.listBoxUser.SelectedItem is User u)
{
await u.Delete(_dbManager);
this._users.Remove(u);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void menuItemNewRole_Click(object sender, RoutedEventArgs e)
{
Role r = new();
this._roles.Add(r);
this.listBoxRoles.SelectedItem = r;
}
private async void menuItemDeleteRole_Click(object sender, RoutedEventArgs e)
{
try
{
if (this.listBoxRoles.SelectedItem is Role r)
{
await r.Delete(_dbManager);
this._roles.Remove(r);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void menuItemNewSecurable_Click(object sender, RoutedEventArgs e)
{
Securable s = new Securable();
_securables.Add(s);
this.listBoxSecurables.SelectedItem = s;
}
private async void menuItemDeleteSecurable_Click(object sender, RoutedEventArgs e)
{
try
{
if (this.listBoxSecurables.SelectedItem is Securable s)
{
await s.Delete(_dbManager);
this._securables.Remove(s);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion
#region Excel import
private async void buttonImportBerths_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx"
};
if (ofd.ShowDialog() ?? false)
{
FileStream stream;
try
{
stream = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
List<Berth> importBerthList = new();
int bCounter = 0;
int pCounter = 0;
try
{
do
{
while (reader.Read())
{
if (reader.FieldCount < 2)
{
throw new InvalidDataException("Sheet must have at least 2 Columns of data");
}
if (reader.IsDBNull(0) && reader.IsDBNull(1)) continue;
string berth_name = "";
if (!reader.IsDBNull(0)) berth_name = reader.GetString(0);
if (berth_name.Equals("Liegeplatz", StringComparison.OrdinalIgnoreCase)) continue;
string participant_name = "";
if (!reader.IsDBNull(1)) participant_name = reader.GetString(1);
// find berth in existing list
if (_berths.Any(predicate: x => (x.Name != null) && x.Name.Equals(berth_name, StringComparison.OrdinalIgnoreCase)))
continue;
Berth b = new Berth();
b.Name = berth_name;
bool found_participant = false;
foreach(Participant p in this._participants)
{
if ((p.Name != null) && p.Name.Contains(participant_name, StringComparison.OrdinalIgnoreCase))
{
b.Participant_Id = p.Id;
found_participant = true;
break;
}
}
if (!found_participant)
{
// create new participant
Participant p = new Participant();
p.Name = participant_name;
p.Type = (uint) Participant.ParticipantType.TERMINAL;
await p.Save(_dbManager);
_participants.Add(p);
pCounter++;
b.Participant_Id = p.Id;
}
await b.Save(_dbManager);
_berths.Add(b);
bCounter++;
}
} while (reader.NextResult());
if((pCounter > 0) || (bCounter > 0))
{
MessageBox.Show($"Imported {bCounter} berths and added {pCounter} participants while doing so");
}
}
catch (Exception ex)
{
MessageBox.Show("Error reading Excel: " + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
stream.Close();
}
}
private void buttonImportShipss_Click(object sender, RoutedEventArgs e)
{
}
#endregion
#region private static helper
private static BitmapImage? LoadImage(byte[] imageData)
{
if (imageData == null || imageData.Length == 0) return null;
var image = new BitmapImage();
using (var mem = new MemoryStream(imageData))
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
image.Freeze();
return image;
}
#endregion
}
}

277
src/RoleEditor/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,277 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace RoleEditor {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RoleEditor.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] about {
get {
object obj = ResourceManager.GetObject("about", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] add {
get {
object obj = ResourceManager.GetObject("add", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] arrow_left_green {
get {
object obj = ResourceManager.GetObject("arrow_left_green", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] businessman {
get {
object obj = ResourceManager.GetObject("businessman", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] delete {
get {
object obj = ResourceManager.GetObject("delete", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] delete2 {
get {
object obj = ResourceManager.GetObject("delete2", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] disk_blue {
get {
object obj = ResourceManager.GetObject("disk_blue", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] document_plain {
get {
object obj = ResourceManager.GetObject("document_plain", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] edit {
get {
object obj = ResourceManager.GetObject("edit", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] floppy_disk_blue {
get {
object obj = ResourceManager.GetObject("floppy_disk_blue", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] id_card {
get {
object obj = ResourceManager.GetObject("id_card", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] key1 {
get {
object obj = ResourceManager.GetObject("key1", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] key1_add {
get {
object obj = ResourceManager.GetObject("key1_add", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] lock_preferences {
get {
object obj = ResourceManager.GetObject("lock_preferences", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] printer {
get {
object obj = ResourceManager.GetObject("printer", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] safe {
get {
object obj = ResourceManager.GetObject("safe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Add.
/// </summary>
internal static string textAdd {
get {
return ResourceManager.GetString("textAdd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Delete.
/// </summary>
internal static string textDelete {
get {
return ResourceManager.GetString("textDelete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Edit.
/// </summary>
internal static string textEdit {
get {
return ResourceManager.GetString("textEdit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export.
/// </summary>
internal static string textExport {
get {
return ResourceManager.GetString("textExport", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Print.
/// </summary>
internal static string textPrint {
get {
return ResourceManager.GetString("textPrint", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Show as text.
/// </summary>
internal static string textShowAsText {
get {
return ResourceManager.GetString("textShowAsText", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="about" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\about.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\add.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="arrow_left_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\arrow_left_green.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="businessman" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\businessman.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="delete" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\delete.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="delete2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\delete2.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="disk_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\disk_blue.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="document_plain" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\document_plain.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="edit" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\edit.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="floppy_disk_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\floppy_disk_blue.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="id_card" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\id_card.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="key1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\key1.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="key1_add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\key1_add.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="lock_preferences" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\lock_preferences.ico;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="printer" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\printer.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="safe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\safe.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="textAdd" xml:space="preserve">
<value>Add</value>
</data>
<data name="textDelete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="textEdit" xml:space="preserve">
<value>Edit</value>
</data>
<data name="textExport" xml:space="preserve">
<value>Export</value>
</data>
<data name="textPrint" xml:space="preserve">
<value>Print</value>
</data>
<data name="textShowAsText" xml:space="preserve">
<value>_Show as text</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Some files were not shown because too many files have changed in this diff Show More