Commit d5a87b98 authored by Marcel's avatar Marcel
Browse files

Initial commit

parents
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
application-dev.yml
# Churchtools to Songbeamer
1. Jar-Datei herunterladen
2. Yml-Datei herunterladen
3. Yml-Datei anpassen
4. Jar-Datei starten
5. Passenden Ablauf doppelklicken
6. Ablauf in Songbeamer öffnen
Details zur [Konfiguration](docs/config.md)
\ No newline at end of file
# Konfiguration
Die Konfiguration wird in der Datei `application.yml` festgelegt. Im folgenden ein Teil der möglichen Konfigurationen:
```
churchtools:
instance: 'mittendrin'
user-id: 12345
user-token: 'in ChurchDB generierte Token hier eintragen'
songbeamer:
agenda-base-folder: 'C:\Users\Benutzername\Documents\SongBeamer'
songs-base-folder: 'C:\Users\Benutzername\Documents\SongBeamer\Songs'
```
### Instance
Die Churchtools Instanz bezeichnet die Subdomain von Churchtools, also den ersten Teil (vor `.church.tools`).
### User-ID
Findet man in ChurchDB rechts unten beim entsprechenden Benutzer.
![Screenshot ChurchDB](img/user-id.png)
### Token
Um einen Token zu erstellen, in ChurchDB den Benutzer wählen.
Dort auf `Berechtigungen` klicken.
Im Popup auf `Login-Token` klicken und den Login-Token kopieren.
### Agenda Base Folder
Hier werden die ausgewählten Abläufe abgespeichert.
### Song Base Folder
Hier wird der in `songs-sub-folder` definierte Ordner angelegt und darin alle Songs gespeichert, welche somit im Songbeamer zur Verfügung stehen.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.apis-stuttgart</groupId>
<artifactId>churchtools-to-songbeamer</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>churchtools-to-songbeamer</name>
<description>Full Agenda translation form ChurchTools to SongBeamer</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/application.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package de.apisstuttgart.churchtoolstosongbeamer;
import de.apisstuttgart.churchtoolstosongbeamer.config.ChurchtoolsConfig;
import de.apisstuttgart.churchtoolstosongbeamer.domain.CtEvent;
import de.apisstuttgart.churchtoolstosongbeamer.service.AgendaConverterService;
import de.apisstuttgart.churchtoolstosongbeamer.service.CtEventService;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import javax.swing.*;
import java.awt.*;
@SpringBootApplication
@CommonsLog
public class ChurchtoolsToSongbeamerApplication {
@Autowired
protected AgendaConverterService agendaConverterService;
@Autowired
protected CtEventService ctEventService;
@Autowired
protected ChurchtoolsConfig churchtoolsConfig;
protected static Container contentPanel;
public static void main(String[] args) {
new SpringApplicationBuilder(ChurchtoolsToSongbeamerApplication.class).headless(false).run(args);
}
@Bean
public CommandLineRunner run() {
return args -> {
initGUI();
// Check config
if (churchtoolsConfig.getUrlBase().isEmpty()) {
showMessage("Bitte Churchtools Instanz richtig konfigurieren");
} else if (churchtoolsConfig.getUserId().isEmpty()) {
showMessage("Bitte die User ID richtig konfigurieren");
} else if (churchtoolsConfig.getUserToken().isEmpty()) {
showMessage("Bitte die User Token richtig konfigurieren");
// Config seems correct
} else {
CtEvent[] ctEvents = ctEventService.getAllEvents();
if (ctEvents != null) {
showEventList(ctEvents, agendaConverterService);
} else {
showMessage("Daten konnten nicht geladen werden.");
}
}
};
}
protected static void initGUI() {
JFrame jFrame = new JFrame("Churchtools to Songbeamer");
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPanel = jFrame.getContentPane();
JLabel jLabelLoading = new JLabel("Bitte warten, die Daten werden geladen.");
contentPanel.add(jLabelLoading);
jFrame.setSize(400, 400);
jFrame.setVisible(true);
}
protected static void showMessage(String message) {
contentPanel.removeAll();
JLabel jLabel = new JLabel(message);
contentPanel.add(jLabel);
contentPanel.revalidate();
contentPanel.repaint();
}
protected static void showEventList(CtEvent[] ctEvents, AgendaConverterService agendaConverterService) {
contentPanel.removeAll();
JList list = new JList(ctEvents);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(selectionEvent -> {
if (!selectionEvent.getValueIsAdjusting()) {
log.info("Selected object for translation is: " + list.getSelectedValue());
agendaConverterService.translate((CtEvent) list.getSelectedValue());
}
});
contentPanel.add(list);
contentPanel.revalidate();
contentPanel.repaint();
}
}
package de.apisstuttgart.churchtoolstosongbeamer.config;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties("churchtools")
@Getter
@Setter
@CommonsLog
public class ChurchtoolsConfig {
protected String instance;
protected String userId;
protected String userToken;
public String getUrlBase() {
if (instance == null || instance.isEmpty()) {
log.error("Please set the churchtools instance");
return "http://localhost";
}
return "https://" + instance + ".church.tools/index.php";
}
}
package de.apisstuttgart.churchtoolstosongbeamer.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties("songbeamer")
@Getter
@Setter
public class SongbeamerConfig {
protected String agendaExtension;
protected String songsExtension;
protected String agendaBaseFolder;
protected String songsBaseFolder;
protected String songsSubFolder;
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(of = {"name"})
public class CtAgenda {
protected String id;
@JsonProperty("bezeichnung")
protected String name;
@JsonProperty("category_id")
protected String categoryId;
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
@Getter
@Setter
public class CtAgendaItem implements Comparable {
protected String id;
@JsonProperty("bezeichnung")
protected String name;
@JsonProperty("category_id")
protected String categoryId;
@JsonProperty("arrangement_id")
protected String arrangementId;
@JsonProperty("header_yn")
protected String titleFlag;
@JsonProperty("preservice_yn")
protected String preService;
protected String responsible;
protected String duration;
protected String note;
@JsonProperty("sortkey")
protected String sortKey;
@JsonProperty("servicegroup")
protected Map<Integer, String> serviceGroupNotes;
public boolean isPreService() {
return "1".equals(preService);
}
public boolean isTitle() {
return "1".equals(titleFlag);
}
public boolean isSong() {
return name.isEmpty() && !arrangementId.isEmpty();
}
public int getSortKey() {
return Integer.parseInt(sortKey);
}
public String getDuration() {
try {
int duration = Integer.parseInt(this.duration);
int minutes = duration / 60;
int seconds = duration % 60;
return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
} catch (Exception e) {
}
return null;
}
@Override
public int compareTo(Object otherObject) {
if (otherObject instanceof CtAgendaItem) {
return getSortKey() - ((CtAgendaItem) otherObject).getSortKey();
}
return 0;
}
@Override
public String toString() {
String duration = getDuration();
if (isSong()) {
return "Song: " + arrangementId + " - " + getDuration();
}
if (isTitle() || duration == null) {
return name;
}
return name + " - " + getDuration();
}
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Getter
@Setter
public class CtEvent implements Comparable {
protected String id;
@JsonProperty("startdate")
protected String start;
@JsonProperty("valid_yn")
protected String valid;
@JsonProperty("bezeichnung")
protected String name;
@JsonProperty("category_id")
protected String categoryId;
protected Boolean agenda;
protected String notizen;
protected String ort;
protected String link;
public LocalDateTime getStartAsDateTime() {
return LocalDateTime.parse(this.start.replaceFirst(" ", "T"));
}
public boolean isPast() {
return LocalDate.now().isBefore(getStartAsDateTime().toLocalDate());
}
@Override
public int compareTo(Object otherObject) {
if (otherObject instanceof CtEvent) {
LocalDateTime thisStart = this.getStartAsDateTime();
LocalDateTime otherStart = ((CtEvent) otherObject).getStartAsDateTime();
return thisStart.compareTo(otherStart);
}
return 0;
}
@Override
public String toString() {
return start + " - " + name;
}
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CtFile {
protected String id;
@JsonProperty("bezeichnung")
protected String name;
protected String filename;
@JsonProperty("domain_type")
protected String domainType;
@JsonProperty("domain_id")
protected String domainId;
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CtResponse<T> {
protected String status;
protected T data;
public boolean isStatusSuccessful() {
return "success".equals(status);
}
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Collection;
import java.util.Map;
@Getter
@Setter
public class CtSong {
protected String id;
@JsonProperty("bezeichnung")
protected String name;
protected String author;
@JsonProperty("songcategory_id")
protected String categoryId;
@JsonProperty("arrangement")
protected Map<Integer, CtSongArrangement> arrangements;
public Collection<CtSongArrangement> getArrangements() {
if (arrangements == null) {
return null;
}
return arrangements.values();
}
public CtSongArrangement getArrangement(int id) {
if (arrangements == null) {
return null;
}
return arrangements.getOrDefault(id, null);
}
}
package de.apisstuttgart.churchtoolstosongbeamer.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@Getter
@Setter
public class CtSongArrangement {
protected String id;
@JsonProperty("bezeichnung")