Add Plan page with day planner

This commit is contained in:
Martin Pander
2022-11-26 18:41:39 +01:00
parent d9b92ab4e9
commit 32346e0aa9
48 changed files with 2400 additions and 148 deletions

View File

@ -1,15 +1,20 @@
openapi: '3.0.2' openapi: '3.0.2'
info: info:
title: Dash API title: Dash API
version: '0.1' version: '0.1'
servers: servers:
- url: http://localhost:18010/api/v1 - url: http://localhost:18010/api/v1
- url: http://localhost:8080/api/v1 - url: http://localhost:8080/api/v1
- url: https://dash.pander.me/api/v1 - url: https://dash.pander.me/api/v1
paths: paths:
/journal/entry/: /journal/entry/:
post: post:
operationId: writeJournalEntry operationId: writeJournalEntry
tags:
- journal
requestBody: requestBody:
required: true required: true
content: content:
@ -22,9 +27,11 @@ paths:
/journal/entry/{date}: /journal/entry/{date}:
get: get:
operationId: getJournalEntryForDate operationId: getJournalEntryForDate
tags:
- journal
responses: responses:
'200': '200':
description: A journal entry for a specific day. description: A journal entry for a specific date.
content: content:
application/json: application/json:
schema: schema:
@ -39,6 +46,8 @@ paths:
example: 2022-02-18 example: 2022-02-18
delete: delete:
operationId: deleteJournalEntryForDate operationId: deleteJournalEntryForDate
tags:
- journal
responses: responses:
'200': '200':
description: Journal entry successfully deleted. description: Journal entry successfully deleted.
@ -50,6 +59,112 @@ paths:
type: string type: string
format: date format: date
example: 2022-02-18 example: 2022-02-18
/plan/day/entry/:
post:
operationId: savePlanForDay
tags:
- plan
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PlanDay'
responses:
'200':
description: Plan successfully written.
/plan/day/entry/{date}:
get:
operationId: getPlanDayForDate
tags:
- plan
responses:
'200':
description: A plan for a specific date.
content:
application/json:
schema:
$ref: '#/components/schemas/PlanDay'
parameters:
- name: date
in: path
required: true
schema:
type: string
format: date
example: 2022-02-18
/plan/week/entry/:
post:
operationId: savePlanForWeek
tags:
- plan
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PlanWeek'
responses:
'200':
description: Plan successfully written.
/plan/week/entry/{date}:
get:
operationId: getPlanWeekForDate
tags:
- plan
responses:
'200':
description: A plan for a specific week.
content:
application/json:
schema:
$ref: '#/components/schemas/PlanWeek'
parameters:
- name: date
in: path
required: true
schema:
type: string
format: date
example: 2022-02-18
/plan/month/entry/:
post:
operationId: savePlanForMonth
tags:
- plan
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PlanMonth'
responses:
'200':
description: Plan successfully written.
/plan/month/entry/{date}:
get:
operationId: getPlanMonthForDate
tags:
- plan
responses:
'200':
description: A plan for a specific week.
content:
application/json:
schema:
$ref: '#/components/schemas/PlanMonth'
parameters:
- name: date
in: path
required: true
schema:
type: string
format: date
example: 2022-02-18
components: components:
schemas: schemas:
JournalEntry: JournalEntry:
@ -96,3 +211,108 @@ components:
journal: journal:
type: string type: string
example: "journal entry 1" example: "journal entry 1"
PlanDay:
type: object
required:
- date
properties:
date:
type: string
format: date
example: 2022-02-18
morning:
type: array
items:
type: string
example:
- "morning 1"
- "morning 2"
- "morning 3"
midday:
type: array
items:
type: string
example:
- "midday 1"
- "midday 2"
- "midday 3"
afternoon:
type: array
items:
type: string
example:
- "afternoon 1"
- "afternoon 2"
- "afternoon 3"
evening:
type: array
items:
type: string
example:
- "evening 1"
- "evening 2"
- "evening 3"
pleasant:
type: array
items:
type: string
example:
- "pleasant 1"
- "pleasant 2"
- "pleasant 3"
reminders:
type: array
items:
type: string
example:
- "reminders 1"
- "reminders 2"
- "reminders 3"
PlanWeek:
type: object
required:
- date
properties:
date:
type: string
format: date
example: 2022-02-18
items:
type: array
items:
$ref: '#/components/schemas/PlanWeekItem'
example: '[{"item": "witem 1"}, {"item": "witem 2", "numTodos":3, "numDone":2}, {"item": "witem 3", "numTodos":2, "numDone":2}]'
PlanWeekItem:
type: object
required:
- item
properties:
item:
type: string
example: 'planWeekItem'
numTodos:
type: integer
format: int32
example: 3
numDone:
type: integer
format: int32
example: 2
PlanMonth:
type: object
required:
- date
properties:
date:
type: string
format: date
example: 2022-02-18
items:
type: array
items:
type: string
example: '["mitem1", "mitem2", "mitem3"]'

View File

@ -13,7 +13,6 @@ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-g go-server \ -g go-server \
-p packageName=dashapi,featureCORS=true,outputAsLibrary=true,sourceFolder=dashapi \ -p packageName=dashapi,featureCORS=true,outputAsLibrary=true,sourceFolder=dashapi \
-o /local/api_server -o /local/api_server
# -p packageName=dashapi,featureCORS=true,outputAsLibrary=true \
rm -rf ../backend/dashapi rm -rf ../backend/dashapi
cp -r ./api_server/dashapi ../backend/ cp -r ./api_server/dashapi ../backend/

View File

@ -28,8 +28,11 @@ func main() {
mapper := mapping.NewMapperImpl() mapper := mapping.NewMapperImpl()
DefaultApiService := service.NewApiService(db, mapper) JournalApiService := service.NewJournalApiService(db, mapper)
DefaultApiController := dashapi.NewDefaultApiController(DefaultApiService) JournalApiController := dashapi.NewJournalApiController(JournalApiService)
PlanApiService := service.NewPlanApiService(db, mapper)
PlanApiController := dashapi.NewPlanApiController(PlanApiService)
cors := handlers.CORS( cors := handlers.CORS(
// handlers.AllowedMethods([]string{"GET", "POST", "DELETE"}), // handlers.AllowedMethods([]string{"GET", "POST", "DELETE"}),
@ -37,7 +40,7 @@ func main() {
handlers.AllowedOrigins([]string{"*"}), handlers.AllowedOrigins([]string{"*"}),
) )
router := dashapi.NewRouter(DefaultApiController) router := dashapi.NewRouter(JournalApiController, PlanApiController)
router.Methods("GET", "POST", "DELETE", "OPTIONS") router.Methods("GET", "POST", "DELETE", "OPTIONS")
log.Printf("Starting server.") log.Printf("Starting server.")

View File

@ -16,22 +16,47 @@ import (
// DefaultApiRouter defines the required methods for binding the api requests to a responses for the DefaultApi // JournalApiRouter defines the required methods for binding the api requests to a responses for the JournalApi
// The DefaultApiRouter implementation should parse necessary information from the http request, // The JournalApiRouter implementation should parse necessary information from the http request,
// pass the data to a DefaultApiServicer to perform the required actions, then write the service results to the http response. // pass the data to a JournalApiServicer to perform the required actions, then write the service results to the http response.
type DefaultApiRouter interface { type JournalApiRouter interface {
DeleteJournalEntryForDate(http.ResponseWriter, *http.Request) DeleteJournalEntryForDate(http.ResponseWriter, *http.Request)
GetJournalEntryForDate(http.ResponseWriter, *http.Request) GetJournalEntryForDate(http.ResponseWriter, *http.Request)
WriteJournalEntry(http.ResponseWriter, *http.Request) WriteJournalEntry(http.ResponseWriter, *http.Request)
} }
// PlanApiRouter defines the required methods for binding the api requests to a responses for the PlanApi
// The PlanApiRouter implementation should parse necessary information from the http request,
// pass the data to a PlanApiServicer to perform the required actions, then write the service results to the http response.
type PlanApiRouter interface {
GetPlanDayForDate(http.ResponseWriter, *http.Request)
GetPlanMonthForDate(http.ResponseWriter, *http.Request)
GetPlanWeekForDate(http.ResponseWriter, *http.Request)
SavePlanForDay(http.ResponseWriter, *http.Request)
SavePlanForMonth(http.ResponseWriter, *http.Request)
SavePlanForWeek(http.ResponseWriter, *http.Request)
}
// DefaultApiServicer defines the api actions for the DefaultApi service // JournalApiServicer defines the api actions for the JournalApi service
// This interface intended to stay up to date with the openapi yaml used to generate it, // This interface intended to stay up to date with the openapi yaml used to generate it,
// while the service implementation can be ignored with the .openapi-generator-ignore file // while the service implementation can be ignored with the .openapi-generator-ignore file
// and updated with the logic required for the API. // and updated with the logic required for the API.
type DefaultApiServicer interface { type JournalApiServicer interface {
DeleteJournalEntryForDate(context.Context, string) (ImplResponse, error) DeleteJournalEntryForDate(context.Context, string) (ImplResponse, error)
GetJournalEntryForDate(context.Context, string) (ImplResponse, error) GetJournalEntryForDate(context.Context, string) (ImplResponse, error)
WriteJournalEntry(context.Context, JournalEntry) (ImplResponse, error) WriteJournalEntry(context.Context, JournalEntry) (ImplResponse, error)
} }
// PlanApiServicer defines the api actions for the PlanApi service
// This interface intended to stay up to date with the openapi yaml used to generate it,
// while the service implementation can be ignored with the .openapi-generator-ignore file
// and updated with the logic required for the API.
type PlanApiServicer interface {
GetPlanDayForDate(context.Context, string) (ImplResponse, error)
GetPlanMonthForDate(context.Context, string) (ImplResponse, error)
GetPlanWeekForDate(context.Context, string) (ImplResponse, error)
SavePlanForDay(context.Context, PlanDay) (ImplResponse, error)
SavePlanForMonth(context.Context, PlanMonth) (ImplResponse, error)
SavePlanForWeek(context.Context, PlanWeek) (ImplResponse, error)
}

View File

@ -17,25 +17,25 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
// DefaultApiController binds http requests to an api service and writes the service results to the http response // JournalApiController binds http requests to an api service and writes the service results to the http response
type DefaultApiController struct { type JournalApiController struct {
service DefaultApiServicer service JournalApiServicer
errorHandler ErrorHandler errorHandler ErrorHandler
} }
// DefaultApiOption for how the controller is set up. // JournalApiOption for how the controller is set up.
type DefaultApiOption func(*DefaultApiController) type JournalApiOption func(*JournalApiController)
// WithDefaultApiErrorHandler inject ErrorHandler into controller // WithJournalApiErrorHandler inject ErrorHandler into controller
func WithDefaultApiErrorHandler(h ErrorHandler) DefaultApiOption { func WithJournalApiErrorHandler(h ErrorHandler) JournalApiOption {
return func(c *DefaultApiController) { return func(c *JournalApiController) {
c.errorHandler = h c.errorHandler = h
} }
} }
// NewDefaultApiController creates a default api controller // NewJournalApiController creates a default api controller
func NewDefaultApiController(s DefaultApiServicer, opts ...DefaultApiOption) Router { func NewJournalApiController(s JournalApiServicer, opts ...JournalApiOption) Router {
controller := &DefaultApiController{ controller := &JournalApiController{
service: s, service: s,
errorHandler: DefaultErrorHandler, errorHandler: DefaultErrorHandler,
} }
@ -47,8 +47,8 @@ func NewDefaultApiController(s DefaultApiServicer, opts ...DefaultApiOption) Rou
return controller return controller
} }
// Routes returns all the api routes for the DefaultApiController // Routes returns all the api routes for the JournalApiController
func (c *DefaultApiController) Routes() Routes { func (c *JournalApiController) Routes() Routes {
return Routes{ return Routes{
{ {
"DeleteJournalEntryForDate", "DeleteJournalEntryForDate",
@ -72,7 +72,7 @@ func (c *DefaultApiController) Routes() Routes {
} }
// DeleteJournalEntryForDate - // DeleteJournalEntryForDate -
func (c *DefaultApiController) DeleteJournalEntryForDate(w http.ResponseWriter, r *http.Request) { func (c *JournalApiController) DeleteJournalEntryForDate(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
dateParam := params["date"] dateParam := params["date"]
@ -88,7 +88,7 @@ func (c *DefaultApiController) DeleteJournalEntryForDate(w http.ResponseWriter,
} }
// GetJournalEntryForDate - // GetJournalEntryForDate -
func (c *DefaultApiController) GetJournalEntryForDate(w http.ResponseWriter, r *http.Request) { func (c *JournalApiController) GetJournalEntryForDate(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
dateParam := params["date"] dateParam := params["date"]
@ -104,7 +104,7 @@ func (c *DefaultApiController) GetJournalEntryForDate(w http.ResponseWriter, r *
} }
// WriteJournalEntry - // WriteJournalEntry -
func (c *DefaultApiController) WriteJournalEntry(w http.ResponseWriter, r *http.Request) { func (c *JournalApiController) WriteJournalEntry(w http.ResponseWriter, r *http.Request) {
journalEntryParam := JournalEntry{} journalEntryParam := JournalEntry{}
d := json.NewDecoder(r.Body) d := json.NewDecoder(r.Body)
d.DisallowUnknownFields() d.DisallowUnknownFields()

View File

@ -15,21 +15,21 @@ import (
"errors" "errors"
) )
// DefaultApiService is a service that implements the logic for the DefaultApiServicer // JournalApiService is a service that implements the logic for the JournalApiServicer
// This service should implement the business logic for every endpoint for the DefaultApi API. // This service should implement the business logic for every endpoint for the JournalApi API.
// Include any external packages or services that will be required by this service. // Include any external packages or services that will be required by this service.
type DefaultApiService struct { type JournalApiService struct {
} }
// NewDefaultApiService creates a default api service // NewJournalApiService creates a default api service
func NewDefaultApiService() DefaultApiServicer { func NewJournalApiService() JournalApiServicer {
return &DefaultApiService{} return &JournalApiService{}
} }
// DeleteJournalEntryForDate - // DeleteJournalEntryForDate -
func (s *DefaultApiService) DeleteJournalEntryForDate(ctx context.Context, date string) (ImplResponse, error) { func (s *JournalApiService) DeleteJournalEntryForDate(ctx context.Context, date string) (ImplResponse, error) {
// TODO - update DeleteJournalEntryForDate with the required logic for this service method. // TODO - update DeleteJournalEntryForDate with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. // Add api_journal_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ... //TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil //return Response(200, nil),nil
@ -38,9 +38,9 @@ func (s *DefaultApiService) DeleteJournalEntryForDate(ctx context.Context, date
} }
// GetJournalEntryForDate - // GetJournalEntryForDate -
func (s *DefaultApiService) GetJournalEntryForDate(ctx context.Context, date string) (ImplResponse, error) { func (s *JournalApiService) GetJournalEntryForDate(ctx context.Context, date string) (ImplResponse, error) {
// TODO - update GetJournalEntryForDate with the required logic for this service method. // TODO - update GetJournalEntryForDate with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. // Add api_journal_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, JournalEntry{}) or use other options such as http.Ok ... //TODO: Uncomment the next line to return response Response(200, JournalEntry{}) or use other options such as http.Ok ...
//return Response(200, JournalEntry{}), nil //return Response(200, JournalEntry{}), nil
@ -49,9 +49,9 @@ func (s *DefaultApiService) GetJournalEntryForDate(ctx context.Context, date str
} }
// WriteJournalEntry - // WriteJournalEntry -
func (s *DefaultApiService) WriteJournalEntry(ctx context.Context, journalEntry JournalEntry) (ImplResponse, error) { func (s *JournalApiService) WriteJournalEntry(ctx context.Context, journalEntry JournalEntry) (ImplResponse, error) {
// TODO - update WriteJournalEntry with the required logic for this service method. // TODO - update WriteJournalEntry with the required logic for this service method.
// Add api_default_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. // Add api_journal_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ... //TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil //return Response(200, nil),nil

210
backend/dashapi/api_plan.go Normal file
View File

@ -0,0 +1,210 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
import (
"encoding/json"
"net/http"
"strings"
"github.com/gorilla/mux"
)
// PlanApiController binds http requests to an api service and writes the service results to the http response
type PlanApiController struct {
service PlanApiServicer
errorHandler ErrorHandler
}
// PlanApiOption for how the controller is set up.
type PlanApiOption func(*PlanApiController)
// WithPlanApiErrorHandler inject ErrorHandler into controller
func WithPlanApiErrorHandler(h ErrorHandler) PlanApiOption {
return func(c *PlanApiController) {
c.errorHandler = h
}
}
// NewPlanApiController creates a default api controller
func NewPlanApiController(s PlanApiServicer, opts ...PlanApiOption) Router {
controller := &PlanApiController{
service: s,
errorHandler: DefaultErrorHandler,
}
for _, opt := range opts {
opt(controller)
}
return controller
}
// Routes returns all the api routes for the PlanApiController
func (c *PlanApiController) Routes() Routes {
return Routes{
{
"GetPlanDayForDate",
strings.ToUpper("Get"),
"/api/v1/plan/day/entry/{date}",
c.GetPlanDayForDate,
},
{
"GetPlanMonthForDate",
strings.ToUpper("Get"),
"/api/v1/plan/month/entry/{date}",
c.GetPlanMonthForDate,
},
{
"GetPlanWeekForDate",
strings.ToUpper("Get"),
"/api/v1/plan/week/entry/{date}",
c.GetPlanWeekForDate,
},
{
"SavePlanForDay",
strings.ToUpper("Post"),
"/api/v1/plan/day/entry/",
c.SavePlanForDay,
},
{
"SavePlanForMonth",
strings.ToUpper("Post"),
"/api/v1/plan/month/entry/",
c.SavePlanForMonth,
},
{
"SavePlanForWeek",
strings.ToUpper("Post"),
"/api/v1/plan/week/entry/",
c.SavePlanForWeek,
},
}
}
// GetPlanDayForDate -
func (c *PlanApiController) GetPlanDayForDate(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
dateParam := params["date"]
result, err := c.service.GetPlanDayForDate(r.Context(), dateParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}
// GetPlanMonthForDate -
func (c *PlanApiController) GetPlanMonthForDate(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
dateParam := params["date"]
result, err := c.service.GetPlanMonthForDate(r.Context(), dateParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}
// GetPlanWeekForDate -
func (c *PlanApiController) GetPlanWeekForDate(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
dateParam := params["date"]
result, err := c.service.GetPlanWeekForDate(r.Context(), dateParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}
// SavePlanForDay -
func (c *PlanApiController) SavePlanForDay(w http.ResponseWriter, r *http.Request) {
planDayParam := PlanDay{}
d := json.NewDecoder(r.Body)
d.DisallowUnknownFields()
if err := d.Decode(&planDayParam); err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
if err := AssertPlanDayRequired(planDayParam); err != nil {
c.errorHandler(w, r, err, nil)
return
}
result, err := c.service.SavePlanForDay(r.Context(), planDayParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}
// SavePlanForMonth -
func (c *PlanApiController) SavePlanForMonth(w http.ResponseWriter, r *http.Request) {
planMonthParam := PlanMonth{}
d := json.NewDecoder(r.Body)
d.DisallowUnknownFields()
if err := d.Decode(&planMonthParam); err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
if err := AssertPlanMonthRequired(planMonthParam); err != nil {
c.errorHandler(w, r, err, nil)
return
}
result, err := c.service.SavePlanForMonth(r.Context(), planMonthParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}
// SavePlanForWeek -
func (c *PlanApiController) SavePlanForWeek(w http.ResponseWriter, r *http.Request) {
planWeekParam := PlanWeek{}
d := json.NewDecoder(r.Body)
d.DisallowUnknownFields()
if err := d.Decode(&planWeekParam); err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
if err := AssertPlanWeekRequired(planWeekParam); err != nil {
c.errorHandler(w, r, err, nil)
return
}
result, err := c.service.SavePlanForWeek(r.Context(), planWeekParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)
}

View File

@ -0,0 +1,93 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
import (
"context"
"net/http"
"errors"
)
// PlanApiService is a service that implements the logic for the PlanApiServicer
// This service should implement the business logic for every endpoint for the PlanApi API.
// Include any external packages or services that will be required by this service.
type PlanApiService struct {
}
// NewPlanApiService creates a default api service
func NewPlanApiService() PlanApiServicer {
return &PlanApiService{}
}
// GetPlanDayForDate -
func (s *PlanApiService) GetPlanDayForDate(ctx context.Context, date string) (ImplResponse, error) {
// TODO - update GetPlanDayForDate with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, PlanDay{}) or use other options such as http.Ok ...
//return Response(200, PlanDay{}), nil
return Response(http.StatusNotImplemented, nil), errors.New("GetPlanDayForDate method not implemented")
}
// GetPlanMonthForDate -
func (s *PlanApiService) GetPlanMonthForDate(ctx context.Context, date string) (ImplResponse, error) {
// TODO - update GetPlanMonthForDate with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, PlanMonth{}) or use other options such as http.Ok ...
//return Response(200, PlanMonth{}), nil
return Response(http.StatusNotImplemented, nil), errors.New("GetPlanMonthForDate method not implemented")
}
// GetPlanWeekForDate -
func (s *PlanApiService) GetPlanWeekForDate(ctx context.Context, date string) (ImplResponse, error) {
// TODO - update GetPlanWeekForDate with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, PlanWeek{}) or use other options such as http.Ok ...
//return Response(200, PlanWeek{}), nil
return Response(http.StatusNotImplemented, nil), errors.New("GetPlanWeekForDate method not implemented")
}
// SavePlanForDay -
func (s *PlanApiService) SavePlanForDay(ctx context.Context, planDay PlanDay) (ImplResponse, error) {
// TODO - update SavePlanForDay with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return Response(http.StatusNotImplemented, nil), errors.New("SavePlanForDay method not implemented")
}
// SavePlanForMonth -
func (s *PlanApiService) SavePlanForMonth(ctx context.Context, planMonth PlanMonth) (ImplResponse, error) {
// TODO - update SavePlanForMonth with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return Response(http.StatusNotImplemented, nil), errors.New("SavePlanForMonth method not implemented")
}
// SavePlanForWeek -
func (s *PlanApiService) SavePlanForWeek(ctx context.Context, planWeek PlanWeek) (ImplResponse, error) {
// TODO - update SavePlanForWeek with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return Response(http.StatusNotImplemented, nil), errors.New("SavePlanForWeek method not implemented")
}

View File

@ -0,0 +1,53 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
type PlanDay struct {
Date string `json:"date"`
Morning []string `json:"morning,omitempty"`
Midday []string `json:"midday,omitempty"`
Afternoon []string `json:"afternoon,omitempty"`
Evening []string `json:"evening,omitempty"`
Pleasant []string `json:"pleasant,omitempty"`
Reminders []string `json:"reminders,omitempty"`
}
// AssertPlanDayRequired checks if the required fields are not zero-ed
func AssertPlanDayRequired(obj PlanDay) error {
elements := map[string]interface{}{
"date": obj.Date,
}
for name, el := range elements {
if isZero := IsZeroValue(el); isZero {
return &RequiredError{Field: name}
}
}
return nil
}
// AssertRecursePlanDayRequired recursively checks if required fields are not zero-ed in a nested slice.
// Accepts only nested slice of PlanDay (e.g. [][]PlanDay), otherwise ErrTypeAssertionError is thrown.
func AssertRecursePlanDayRequired(objSlice interface{}) error {
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
aPlanDay, ok := obj.(PlanDay)
if !ok {
return ErrTypeAssertionError
}
return AssertPlanDayRequired(aPlanDay)
})
}

View File

@ -0,0 +1,43 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
type PlanMonth struct {
Date string `json:"date"`
Items []string `json:"items,omitempty"`
}
// AssertPlanMonthRequired checks if the required fields are not zero-ed
func AssertPlanMonthRequired(obj PlanMonth) error {
elements := map[string]interface{}{
"date": obj.Date,
}
for name, el := range elements {
if isZero := IsZeroValue(el); isZero {
return &RequiredError{Field: name}
}
}
return nil
}
// AssertRecursePlanMonthRequired recursively checks if required fields are not zero-ed in a nested slice.
// Accepts only nested slice of PlanMonth (e.g. [][]PlanMonth), otherwise ErrTypeAssertionError is thrown.
func AssertRecursePlanMonthRequired(objSlice interface{}) error {
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
aPlanMonth, ok := obj.(PlanMonth)
if !ok {
return ErrTypeAssertionError
}
return AssertPlanMonthRequired(aPlanMonth)
})
}

View File

@ -0,0 +1,48 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
type PlanWeek struct {
Date string `json:"date"`
Items []PlanWeekItem `json:"items,omitempty"`
}
// AssertPlanWeekRequired checks if the required fields are not zero-ed
func AssertPlanWeekRequired(obj PlanWeek) error {
elements := map[string]interface{}{
"date": obj.Date,
}
for name, el := range elements {
if isZero := IsZeroValue(el); isZero {
return &RequiredError{Field: name}
}
}
for _, el := range obj.Items {
if err := AssertPlanWeekItemRequired(el); err != nil {
return err
}
}
return nil
}
// AssertRecursePlanWeekRequired recursively checks if required fields are not zero-ed in a nested slice.
// Accepts only nested slice of PlanWeek (e.g. [][]PlanWeek), otherwise ErrTypeAssertionError is thrown.
func AssertRecursePlanWeekRequired(objSlice interface{}) error {
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
aPlanWeek, ok := obj.(PlanWeek)
if !ok {
return ErrTypeAssertionError
}
return AssertPlanWeekRequired(aPlanWeek)
})
}

View File

@ -0,0 +1,45 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package dashapi
type PlanWeekItem struct {
Item string `json:"item"`
NumTodos int32 `json:"numTodos,omitempty"`
NumDone int32 `json:"numDone,omitempty"`
}
// AssertPlanWeekItemRequired checks if the required fields are not zero-ed
func AssertPlanWeekItemRequired(obj PlanWeekItem) error {
elements := map[string]interface{}{
"item": obj.Item,
}
for name, el := range elements {
if isZero := IsZeroValue(el); isZero {
return &RequiredError{Field: name}
}
}
return nil
}
// AssertRecursePlanWeekItemRequired recursively checks if required fields are not zero-ed in a nested slice.
// Accepts only nested slice of PlanWeekItem (e.g. [][]PlanWeekItem), otherwise ErrTypeAssertionError is thrown.
func AssertRecursePlanWeekItemRequired(objSlice interface{}) error {
return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error {
aPlanWeekItem, ok := obj.(PlanWeekItem)
if !ok {
return ErrTypeAssertionError
}
return AssertPlanWeekItemRequired(aPlanWeekItem)
})
}

View File

@ -1,11 +0,0 @@
package database
import (
"time"
// "github.com/moustachioed/dash/backend/database/models"
)
type Database interface {
WriteJournalEntry(interface{}) error
GetJournalEntryForDate(time.Time) (interface{}, error)
}

View File

@ -0,0 +1,25 @@
package models
import (
"gorm.io/datatypes"
)
type PlanDay struct {
Date datatypes.Date `gorm:"primaryKey"`
Morning datatypes.JSON
Midday datatypes.JSON
Afternoon datatypes.JSON
Evening datatypes.JSON
Pleasant datatypes.JSON
Reminders datatypes.JSON
}
type PlanWeek struct {
Date datatypes.Date `gorm:"primaryKey"`
Items datatypes.JSON
}
type PlanMonth struct {
Date datatypes.Date `gorm:"primaryKey"`
Items datatypes.JSON
}

View File

@ -11,13 +11,14 @@ import (
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"github.com/moustachioed/dash/backend/database/models" "github.com/moustachioed/dash/backend/database/models"
"github.com/moustachioed/dash/backend/service"
) )
type PgDatabase struct { type PgDatabase struct {
Db *gorm.DB Db *gorm.DB
} }
func NewPgDatabase(host string, user string, password string, database string, port uint16) (Database, error) { func NewPgDatabase(host string, user string, password string, database string, port uint16) (service.DataStore, error) {
db := &PgDatabase{} db := &PgDatabase{}
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable", host, user, password, database, port) dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable", host, user, password, database, port)
@ -38,6 +39,9 @@ func NewPgDatabase(host string, user string, password string, database string, p
func (db *PgDatabase) migrate() { func (db *PgDatabase) migrate() {
db.Db.AutoMigrate(&models.Journal{}) db.Db.AutoMigrate(&models.Journal{})
db.Db.AutoMigrate(&models.PlanDay{})
db.Db.AutoMigrate(&models.PlanWeek{})
db.Db.AutoMigrate(&models.PlanMonth{})
} }
func (db *PgDatabase) WriteJournalEntry(entry interface{}) error { func (db *PgDatabase) WriteJournalEntry(entry interface{}) error {
@ -57,3 +61,57 @@ func (db *PgDatabase) GetJournalEntryForDate(date time.Time) (interface{}, error
return entry, nil return entry, nil
} }
func (db *PgDatabase) WritePlanDay(entry interface{}) error {
planDay := entry.(models.PlanDay)
err := db.Db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&planDay).Error
if err != nil {
log.Print("Error writing plan day to database.")
return err
}
return nil
}
func (db *PgDatabase) GetPlanDayForDate(date time.Time) (interface{}, error) {
entry := models.PlanDay{Date: datatypes.Date(date)}
db.Db.First(&entry)
return entry, nil
}
func (db *PgDatabase) WritePlanWeek(entry interface{}) error {
planWeek := entry.(models.PlanWeek)
err := db.Db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&planWeek).Error
if err != nil {
log.Print("Error writing plan week to database.")
return err
}
return nil
}
func (db *PgDatabase) GetPlanWeekForDate(date time.Time) (interface{}, error) {
entry := models.PlanWeek{Date: datatypes.Date(date)}
db.Db.First(&entry)
return entry, nil
}
func (db *PgDatabase) WritePlanMonth(entry interface{}) error {
planMonth := entry.(models.PlanMonth)
err := db.Db.Clauses(clause.OnConflict{UpdateAll: true}).Create(&planMonth).Error
if err != nil {
log.Print("Error writing plan month to database.")
return err
}
return nil
}
func (db *PgDatabase) GetPlanMonthForDate(date time.Time) (interface{}, error) {
entry := models.PlanMonth{Date: datatypes.Date(date)}
db.Db.First(&entry)
return entry, nil
}

View File

@ -2,13 +2,20 @@ package mapping
import ( import (
"time" "time"
// api "github.com/moustachioed/dash/backend/dashapi"
// db "github.com/moustachioed/dash/backend/database/models"
) )
type Mapper interface { type Mapper interface {
JournalApiToDb(api interface{}) (db interface{}) JournalApiToDs(api interface{}) (db interface{})
JournalDbToApi(db interface{}) (api interface{}) JournalDsToApi(db interface{}) (api interface{})
PlanDayApiToDs(api interface{}) (db interface{})
PlanDayDsToApi(db interface{}) (api interface{})
PlanWeekApiToDs(api interface{}) (db interface{})
PlanWeekDsToApi(db interface{}) (api interface{})
PlanMonthApiToDs(api interface{}) (db interface{})
PlanMonthDsToApi(db interface{}) (api interface{})
StringToDate(string) (time.Time, error) StringToDate(string) (time.Time, error)
DateToString(time.Time) string DateToString(time.Time) string

View File

@ -17,9 +17,9 @@ func NewMapperImpl() Mapper {
return MapperImpl{} return MapperImpl{}
} }
func (mapper MapperImpl) JournalApiToDb(am interface{}) interface{} { func (mapper MapperImpl) JournalApiToDs(am interface{}) interface{} {
apimodel := am.(api.JournalEntry) apimodel := am.(api.JournalEntry)
date, err := time.Parse("2006-01-02", apimodel.Date) date, err := mapper.StringToDate(apimodel.Date)
if err != nil { if err != nil {
log.Printf("[ERROR] Could not parse date `%s`", apimodel.Date) log.Printf("[ERROR] Could not parse date `%s`", apimodel.Date)
} }
@ -54,7 +54,7 @@ func (mapper MapperImpl) JournalApiToDb(am interface{}) interface{} {
} }
} }
func (mapper MapperImpl) JournalDbToApi(dm interface{}) interface{} { func (mapper MapperImpl) JournalDsToApi(dm interface{}) interface{} {
dbmodel := dm.(db.Journal) dbmodel := dm.(db.Journal)
dateValue, err := dbmodel.Date.Value() dateValue, err := dbmodel.Date.Value()
@ -62,7 +62,8 @@ func (mapper MapperImpl) JournalDbToApi(dm interface{}) interface{} {
if err != nil { if err != nil {
date = "" date = ""
} else { } else {
date = dateValue.(time.Time).Format("2006-01-02") // date = dateValue.(time.Time).Format("2006-01-02")
date = mapper.DateToString(dateValue.(time.Time))
} }
var thankful []string var thankful []string
@ -74,19 +75,19 @@ func (mapper MapperImpl) JournalDbToApi(dm interface{}) interface{} {
var lookingForward []string var lookingForward []string
err = json.Unmarshal(dbmodel.LookingForward, &lookingForward) err = json.Unmarshal(dbmodel.LookingForward, &lookingForward)
if err != nil { if err != nil {
thankful = nil lookingForward = nil
} }
var beenGreat []string var beenGreat []string
err = json.Unmarshal(dbmodel.BeenGreat, &beenGreat) err = json.Unmarshal(dbmodel.BeenGreat, &beenGreat)
if err != nil { if err != nil {
thankful = nil beenGreat = nil
} }
var doBetter []string var doBetter []string
err = json.Unmarshal(dbmodel.DoBetter, &doBetter) err = json.Unmarshal(dbmodel.DoBetter, &doBetter)
if err != nil { if err != nil {
thankful = nil doBetter = nil
} }
return api.JournalEntry{ return api.JournalEntry{
@ -99,11 +100,133 @@ func (mapper MapperImpl) JournalDbToApi(dm interface{}) interface{} {
} }
} }
func (mapper MapperImpl) PlanDayApiToDs(am interface{}) interface{} {
apimodel := am.(api.PlanDay)
date, err := mapper.StringToDate(apimodel.Date)
if err != nil {
log.Printf("[ERROR] Could not parse date `%s`", apimodel.Date)
}
morning, err := json.Marshal(apimodel.Morning)
if err != nil {
morning = nil
}
midday, err := json.Marshal(apimodel.Midday)
if err != nil {
midday = nil
}
afternoon, err := json.Marshal(apimodel.Afternoon)
if err != nil {
afternoon = nil
}
evening, err := json.Marshal(apimodel.Evening)
if err != nil {
evening = nil
}
pleasant, err := json.Marshal(apimodel.Pleasant)
if err != nil {
pleasant = nil
}
reminders, err := json.Marshal(apimodel.Reminders)
if err != nil {
reminders = nil
}
return db.PlanDay{
Date: datatypes.Date(date),
Morning: datatypes.JSON(morning),
Midday: datatypes.JSON(midday),
Afternoon: datatypes.JSON(afternoon),
Evening: datatypes.JSON(evening),
Pleasant: datatypes.JSON(pleasant),
Reminders: datatypes.JSON(reminders),
}
}
func (mapper MapperImpl) PlanDayDsToApi(dm interface{}) interface{} {
dbmodel := dm.(db.PlanDay)
dateValue, err := dbmodel.Date.Value()
var date string
if err != nil {
date = ""
} else {
date = mapper.DateToString(dateValue.(time.Time))
}
var morning []string
err = json.Unmarshal(dbmodel.Morning, &morning)
if err != nil {
morning = nil
}
var midday []string
err = json.Unmarshal(dbmodel.Midday, &midday)
if err != nil {
midday = nil
}
var afternoon []string
err = json.Unmarshal(dbmodel.Afternoon, &afternoon)
if err != nil {
afternoon = nil
}
var evening []string
err = json.Unmarshal(dbmodel.Evening, &evening)
if err != nil {
evening = nil
}
var pleasant []string
err = json.Unmarshal(dbmodel.Pleasant, &pleasant)
if err != nil {
pleasant = nil
}
var reminders []string
err = json.Unmarshal(dbmodel.Reminders, &reminders)
if err != nil {
reminders = nil
}
return api.PlanDay{
Date: date,
Morning: morning,
Midday: midday,
Afternoon: afternoon,
Evening: evening,
Pleasant: pleasant,
Reminders: reminders,
}
}
func (mapper MapperImpl) PlanWeekApiToDs(api interface{}) (db interface{}) {
return new(interface{})
}
func (mapper MapperImpl) PlanWeekDsToApi(api interface{}) (db interface{}) {
return new(interface{})
}
func (mapper MapperImpl) PlanMonthApiToDs(api interface{}) (db interface{}) {
return new(interface{})
}
func (mapper MapperImpl) PlanMonthDsToApi(api interface{}) (db interface{}) {
return new(interface{})
}
func (mapper MapperImpl) StringToDate(dateString string) (time.Time, error) { func (mapper MapperImpl) StringToDate(dateString string) (time.Time, error) {
date, err := time.Parse("2006-01-02", dateString) date, err := time.Parse("2006-01-02", dateString)
if err != nil { if err != nil {
log.Printf("[ERROR] Could not parse date string %s", dateString) log.Printf("[ERROR] Could not parse date string %s", dateString)
return time.Now(), err return time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), err
} }
return date, nil return date, nil
} }

View File

@ -2,6 +2,7 @@ package mapping
import ( import (
"encoding/json" "encoding/json"
"reflect"
"testing" "testing"
"time" "time"
@ -22,7 +23,7 @@ func TestJournalApiToDbFullObject(t *testing.T) {
Journal: "jtest", Journal: "jtest",
} }
db := mapper.JournalApiToDb(api).(models.Journal) db := mapper.JournalApiToDs(api).(models.Journal)
gotDate, _ := db.Date.Value() gotDate, _ := db.Date.Value()
got := gotDate.(time.Time).Format("2006-01-02") got := gotDate.(time.Time).Format("2006-01-02")
@ -80,7 +81,7 @@ func TestJournalApiToDbPartialObject(t *testing.T) {
Journal: "", Journal: "",
} }
db := mapper.JournalApiToDb(api).(models.Journal) db := mapper.JournalApiToDs(api).(models.Journal)
gotDate, _ := db.Date.Value() gotDate, _ := db.Date.Value()
got := gotDate.(time.Time).Format("2006-01-02") got := gotDate.(time.Time).Format("2006-01-02")
@ -145,7 +146,7 @@ func TestJournalDbToApiFullObject(t *testing.T) {
Journal: journal, Journal: journal,
} }
api := mapper.JournalDbToApi(db).(dashapi.JournalEntry) api := mapper.JournalDsToApi(db).(dashapi.JournalEntry)
got, _ := json.Marshal(api.Date) got, _ := json.Marshal(api.Date)
wantDate := "\"2022-02-18\"" wantDate := "\"2022-02-18\""
@ -209,7 +210,7 @@ func TestJournalDbToApiPartialObject(t *testing.T) {
Journal: journal, Journal: journal,
} }
api := mapper.JournalDbToApi(db).(dashapi.JournalEntry) api := mapper.JournalDsToApi(db).(dashapi.JournalEntry)
got, _ := json.Marshal(api.Date) got, _ := json.Marshal(api.Date)
wantDate := "\"2022-02-18\"" wantDate := "\"2022-02-18\""
@ -253,3 +254,229 @@ func TestJournalDbToApiPartialObject(t *testing.T) {
t.Errorf("Mapped string %s not equal want string %s", gotJournal, wantJournal) t.Errorf("Mapped string %s not equal want string %s", gotJournal, wantJournal)
} }
} }
func TestMapperImpl_PlanDayApiToDs(t *testing.T) {
date, _ := time.Parse("2006-01-02", "2022-02-18")
morning, _ := json.Marshal([]string{"motest1", "motest2", "motest3"})
midday, _ := json.Marshal([]string{"mitest1", "mitest2", "mitest3"})
afternoon, _ := json.Marshal([]string{"antest1", "antest2", "antest3"})
evening, _ := json.Marshal([]string{"etest1", "etest2", "etest3"})
pleasant, _ := json.Marshal([]string{"ptest1", "ptest2", "ptest3"})
reminders, _ := json.Marshal([]string{"rtest1", "rtest2", "rtest3"})
empty, _ := json.Marshal(nil)
type args struct {
am interface{}
}
tests := []struct {
name string
mapper MapperImpl
args args
want interface{}
}{
{
name: "Full Object",
mapper: MapperImpl{},
args: args{
am: dashapi.PlanDay{
Date: "2022-02-18",
Morning: []string{"motest1", "motest2", "motest3"},
Midday: []string{"mitest1", "mitest2", "mitest3"},
Afternoon: []string{"antest1", "antest2", "antest3"},
Evening: []string{"etest1", "etest2", "etest3"},
Pleasant: []string{"ptest1", "ptest2", "ptest3"},
Reminders: []string{"rtest1", "rtest2", "rtest3"},
}},
want: models.PlanDay{
Date: datatypes.Date(date),
Morning: datatypes.JSON(morning),
Midday: datatypes.JSON(midday),
Afternoon: datatypes.JSON(afternoon),
Evening: datatypes.JSON(evening),
Pleasant: datatypes.JSON(pleasant),
Reminders: datatypes.JSON(reminders),
},
},
{
name: "Partial Object",
mapper: MapperImpl{},
args: args{
am: dashapi.PlanDay{
Date: "2022-02-18",
Morning: []string{"motest1", "motest2", "motest3"},
Midday: nil,
Afternoon: nil,
Evening: nil,
Pleasant: []string{"ptest1", "ptest2", "ptest3"},
Reminders: nil,
}},
want: models.PlanDay{
Date: datatypes.Date(date),
Morning: datatypes.JSON(morning),
Midday: datatypes.JSON(empty),
Afternoon: datatypes.JSON(empty),
Evening: datatypes.JSON(empty),
Pleasant: datatypes.JSON(pleasant),
Reminders: datatypes.JSON(empty),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mapper := MapperImpl{}
if got := mapper.PlanDayApiToDs(tt.args.am); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MapperImpl.PlanDayApiToDs() = %v, want %v", got, tt.want)
}
})
}
}
func TestMapperImpl_PlanDayDsToApi(t *testing.T) {
date, _ := time.Parse("2006-01-02", "2022-02-18")
morning, _ := json.Marshal([]string{"motest1", "motest2", "motest3"})
midday, _ := json.Marshal([]string{"mitest1", "mitest2", "mitest3"})
afternoon, _ := json.Marshal([]string{"antest1", "antest2", "antest3"})
evening, _ := json.Marshal([]string{"etest1", "etest2", "etest3"})
pleasant, _ := json.Marshal([]string{"ptest1", "ptest2", "ptest3"})
reminders, _ := json.Marshal([]string{"rtest1", "rtest2", "rtest3"})
empty, _ := json.Marshal(nil)
type args struct {
dm interface{}
}
tests := []struct {
name string
mapper MapperImpl
args args
want interface{}
}{
{
name: "Full Object",
mapper: MapperImpl{},
args: args{
dm: models.PlanDay{
Date: datatypes.Date(date),
Morning: datatypes.JSON(morning),
Midday: datatypes.JSON(midday),
Afternoon: datatypes.JSON(afternoon),
Evening: datatypes.JSON(evening),
Pleasant: datatypes.JSON(pleasant),
Reminders: datatypes.JSON(reminders),
}},
want: dashapi.PlanDay{
Date: "2022-02-18",
Morning: []string{"motest1", "motest2", "motest3"},
Midday: []string{"mitest1", "mitest2", "mitest3"},
Afternoon: []string{"antest1", "antest2", "antest3"},
Evening: []string{"etest1", "etest2", "etest3"},
Pleasant: []string{"ptest1", "ptest2", "ptest3"},
Reminders: []string{"rtest1", "rtest2", "rtest3"},
},
},
{
name: "Partial Object",
mapper: MapperImpl{},
args: args{
dm: models.PlanDay{
Date: datatypes.Date(date),
Morning: datatypes.JSON(morning),
Midday: datatypes.JSON(empty),
Afternoon: datatypes.JSON(afternoon),
Evening: datatypes.JSON(empty),
Pleasant: datatypes.JSON(pleasant),
Reminders: datatypes.JSON(empty),
}},
want: dashapi.PlanDay{
Date: "2022-02-18",
Morning: []string{"motest1", "motest2", "motest3"},
Midday: nil,
Afternoon: []string{"antest1", "antest2", "antest3"},
Evening: nil,
Pleasant: []string{"ptest1", "ptest2", "ptest3"},
Reminders: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mapper := MapperImpl{}
if got := mapper.PlanDayDsToApi(tt.args.dm); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MapperImpl.PlanDayDsToApi() = %v, want %v", got, tt.want)
}
})
}
}
func TestMapperImpl_StringToDate(t *testing.T) {
type args struct {
dateString string
}
tests := []struct {
name string
mapper MapperImpl
args args
want time.Time
wantErr bool
}{
{
name: "Well-formed date",
mapper: MapperImpl{},
args: args{
dateString: "1987-02-18",
},
want: time.Date(1987, 2, 18, 0, 0, 0, 0, time.UTC),
wantErr: false,
},
{
name: "False string",
mapper: MapperImpl{},
args: args{
dateString: "1987-02-18'T'13:02:18",
},
want: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mapper := MapperImpl{}
got, err := mapper.StringToDate(tt.args.dateString)
if (err != nil) != tt.wantErr {
t.Errorf("MapperImpl.StringToDate() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("MapperImpl.StringToDate() = %v, want %v", got, tt.want)
}
})
}
}
func TestMapperImpl_DateToString(t *testing.T) {
type args struct {
date time.Time
}
tests := []struct {
name string
mapper MapperImpl
args args
want string
}{
{
name: "Well-formed date",
mapper: MapperImpl{},
args: args{
date: time.Date(1987, 2, 18, 0, 0, 0, 0, time.UTC),
},
want: "1987-02-18",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mapper := MapperImpl{}
if got := mapper.DateToString(tt.args.date); got != tt.want {
t.Errorf("MapperImpl.DateToString() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -0,0 +1,67 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package service
import (
"context"
"errors"
"log"
"net/http"
"github.com/moustachioed/dash/backend/dashapi"
"github.com/moustachioed/dash/backend/mapping"
)
// JournalApiService is a service that implements the logic for the JournalApiServicer
type JournalApiService struct {
ds DataStore
mapper mapping.Mapper
}
// NewJournalApiService creates a default api service
func NewJournalApiService(ds DataStore, mapper mapping.Mapper) dashapi.JournalApiServicer {
service := JournalApiService{
ds: ds,
mapper: mapper,
}
return &service
}
// DeleteJournalEntryForDate -
func (s *JournalApiService) DeleteJournalEntryForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
// TODO - update DeleteJournalEntryForDate with the required logic for this service method.
// Add api_journal_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("DeleteJournalEntryForDate method not implemented")
}
// GetJournalEntryForDate -
func (s *JournalApiService) GetJournalEntryForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
d, err := s.mapper.StringToDate(date)
if err != nil {
log.Fatal(err)
}
dbEntry, _ := s.ds.GetJournalEntryForDate(d)
journal := s.mapper.JournalDsToApi(dbEntry)
return dashapi.Response(200, journal), nil
}
// WriteJournalEntry -
func (s *JournalApiService) WriteJournalEntry(ctx context.Context, journalEntry dashapi.JournalEntry) (dashapi.ImplResponse, error) {
journal := s.mapper.JournalApiToDs(journalEntry)
s.ds.WriteJournalEntry(journal)
return dashapi.Response(200, nil), nil
}

View File

@ -0,0 +1,102 @@
/*
* Dash API
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 0.1
* Generated by: OpenAPI Generator (https://openapi-generator.tech)
*/
package service
import (
"context"
"errors"
"log"
"net/http"
"github.com/moustachioed/dash/backend/dashapi"
"github.com/moustachioed/dash/backend/mapping"
)
// PlanApiService is a service that implements the logic for the PlanApiServicer
// This service should implement the business logic for every endpoint for the PlanApi API.
// Include any external packages or services that will be required by this service.
type PlanApiService struct {
ds DataStore
mapper mapping.Mapper
}
// NewPlanApiService creates a default api service
func NewPlanApiService(ds DataStore, mapper mapping.Mapper) dashapi.PlanApiServicer {
service := PlanApiService{
ds: ds,
mapper: mapper,
}
return &service
}
// GetPlanDayForDate -
func (s *PlanApiService) GetPlanDayForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
d, err := s.mapper.StringToDate(date)
if err != nil {
log.Fatal(err)
}
dbEntry, _ := s.ds.GetPlanDayForDate(d)
planDay := s.mapper.PlanDayDsToApi(dbEntry)
return dashapi.Response(200, planDay), nil
}
// GetPlanMonthForDate -
func (s *PlanApiService) GetPlanMonthForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
// TODO - update GetPlanMonthForDate with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, PlanMonth{}) or use other options such as http.Ok ...
//return Response(200, PlanMonth{}), nil
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("GetPlanMonthForDate method not implemented")
}
// GetPlanWeekForDate -
func (s *PlanApiService) GetPlanWeekForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
// TODO - update GetPlanWeekForDate with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, PlanWeek{}) or use other options such as http.Ok ...
//return Response(200, PlanWeek{}), nil
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("GetPlanWeekForDate method not implemented")
}
// SavePlanForDay -
func (s *PlanApiService) SavePlanForDay(ctx context.Context, planDay dashapi.PlanDay) (dashapi.ImplResponse, error) {
plan := s.mapper.PlanDayApiToDs(planDay)
s.ds.WritePlanDay(plan)
return dashapi.Response(200, nil), nil
}
// SavePlanForMonth -
func (s *PlanApiService) SavePlanForMonth(ctx context.Context, planMonth dashapi.PlanMonth) (dashapi.ImplResponse, error) {
// TODO - update SavePlanForMonth with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("SavePlanForMonth method not implemented")
}
// SavePlanForWeek -
func (s *PlanApiService) SavePlanForWeek(ctx context.Context, planWeek dashapi.PlanWeek) (dashapi.ImplResponse, error) {
// TODO - update SavePlanForWeek with the required logic for this service method.
// Add api_plan_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.
//TODO: Uncomment the next line to return response Response(200, {}) or use other options such as http.Ok ...
//return Response(200, nil),nil
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("SavePlanForWeek method not implemented")
}

View File

@ -1,54 +0,0 @@
package service
import (
"context"
"errors"
"log"
"net/http"
"github.com/moustachioed/dash/backend/dashapi"
"github.com/moustachioed/dash/backend/database"
"github.com/moustachioed/dash/backend/mapping"
)
// ApiService is a service that implements the logic for the DefaultApiServicer
// This service should implement the business logic for every endpoint for the Api API.
// Include any external packages or services that will be required by this service.
type ApiService struct {
db database.Database
mapper mapping.Mapper
}
// NewApiService creates a default api service
func NewApiService(db database.Database, mapper mapping.Mapper) dashapi.DefaultApiServicer {
service := ApiService{
db: db,
mapper: mapper,
}
return &service
}
// GetJournalEntryForDate -
func (s *ApiService) GetJournalEntryForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
d, err := s.mapper.StringToDate(date)
if err != nil {
log.Fatal(err)
}
dbEntry, _ := s.db.GetJournalEntryForDate(d)
journal := s.mapper.JournalDbToApi(dbEntry)
return dashapi.Response(200, journal), nil
}
// WriteJournalEntryForDate -
func (s *ApiService) WriteJournalEntry(ctx context.Context, journalEntry dashapi.JournalEntry) (dashapi.ImplResponse, error) {
journal := s.mapper.JournalApiToDb(journalEntry)
s.db.WriteJournalEntry(journal)
return dashapi.Response(200, nil), nil
}
func (s *ApiService) DeleteJournalEntryForDate(ctx context.Context, date string) (dashapi.ImplResponse, error) {
return dashapi.Response(http.StatusNotImplemented, nil), errors.New("DeleteJournalEntryForDate method not implemented")
}

View File

@ -0,0 +1,19 @@
package service
import (
"time"
)
type DataStore interface {
WriteJournalEntry(interface{}) error
GetJournalEntryForDate(time.Time) (interface{}, error)
WritePlanDay(interface{}) error
GetPlanDayForDate(time.Time) (interface{}, error)
WritePlanWeek(interface{}) error
GetPlanWeekForDate(time.Time) (interface{}, error)
WritePlanMonth(interface{}) error
GetPlanMonthForDate(time.Time) (interface{}, error)
}

View File

@ -10,8 +10,10 @@
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"shortid": "^2.2.16",
"svelte": "^3.49.0", "svelte": "^3.49.0",
"svelte-check": "^2.8.0", "svelte-check": "^2.8.0",
"svelte-dnd-action": "^0.9.21",
"svelte-preprocess": "^4.10.7", "svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"typescript": "^4.6.4", "typescript": "^4.6.4",
@ -1202,6 +1204,21 @@
"rimraf": "^2.5.2" "rimraf": "^2.5.2"
} }
}, },
"node_modules/shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"dev": true,
"dependencies": {
"nanoid": "^2.1.0"
}
},
"node_modules/shortid/node_modules/nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==",
"dev": true
},
"node_modules/sorcery": { "node_modules/sorcery": {
"version": "0.10.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@ -1287,6 +1304,12 @@
"svelte": "^3.24.0" "svelte": "^3.24.0"
} }
}, },
"node_modules/svelte-dnd-action": {
"version": "0.9.21",
"resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.21.tgz",
"integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==",
"dev": true
},
"node_modules/svelte-hmr": { "node_modules/svelte-hmr": {
"version": "0.14.12", "version": "0.14.12",
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz",
@ -2214,6 +2237,23 @@
"rimraf": "^2.5.2" "rimraf": "^2.5.2"
} }
}, },
"shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"dev": true,
"requires": {
"nanoid": "^2.1.0"
},
"dependencies": {
"nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==",
"dev": true
}
}
},
"sorcery": { "sorcery": {
"version": "0.10.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@ -2275,6 +2315,12 @@
"typescript": "*" "typescript": "*"
} }
}, },
"svelte-dnd-action": {
"version": "0.9.21",
"resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.21.tgz",
"integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==",
"dev": true
},
"svelte-hmr": { "svelte-hmr": {
"version": "0.14.12", "version": "0.14.12",
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz",

View File

@ -12,8 +12,10 @@
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"shortid": "^2.2.16",
"svelte": "^3.49.0", "svelte": "^3.49.0",
"svelte-check": "^2.8.0", "svelte-check": "^2.8.0",
"svelte-dnd-action": "^0.9.21",
"svelte-preprocess": "^4.10.7", "svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"typescript": "^4.6.4", "typescript": "^4.6.4",

View File

@ -27,7 +27,7 @@ a:hover {
body { body {
margin: 0; margin: 0;
display: flex; display: flex;
place-items: center; place-items: top;
min-width: 320px; min-width: 320px;
min-height: 100vh; min-height: 100vh;
} }

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M64 360c30.9 0 56 25.1 56 56s-25.1 56-56 56s-56-25.1-56-56s25.1-56 56-56zm0-160c30.9 0 56 25.1 56 56s-25.1 56-56 56s-56-25.1-56-56s25.1-56 56-56zM120 96c0 30.9-25.1 56-56 56S8 126.9 8 96S33.1 40 64 40s56 25.1 56 56z"/></svg>

After

Width:  |  Height:  |  Size: 463 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M560 160c44.2 0 80-35.8 80-80s-35.8-80-80-80s-80 35.8-80 80s35.8 80 80 80zM55.9 512H381.1h75H578.9c33.8 0 61.1-27.4 61.1-61.1c0-11.2-3.1-22.2-8.9-31.8l-132-216.3C495 196.1 487.8 192 480 192s-15 4.1-19.1 10.7l-48.2 79L286.8 81c-6.6-10.6-18.3-17-30.8-17s-24.1 6.4-30.8 17L8.6 426.4C3 435.3 0 445.6 0 456.1C0 487 25 512 55.9 512z"/></svg>

After

Width:  |  Height:  |  Size: 574 B

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { curTab } from '../stores/appStore'; import { curTab } from '../stores/appStore';
import Journal from './journal/Journal.svelte'; import Journal from './journal/Journal.svelte';
import Plan from './Plan.svelte'; import Plan from './plan/Plan.svelte';
</script> </script>
<div class="main"> <div class="main">

View File

@ -11,5 +11,13 @@
<style> <style>
.Main { .Main {
vertical-align: top; vertical-align: top;
width: 100%;
/* position: relative; */
}
@media screen and (min-width: 550px) {
.Main {
width: 550px;
}
} }
</style> </style>

View File

@ -1,3 +0,0 @@
<div style="width:100%;">
<h1>Plan</h1>
</div>

View File

@ -1,9 +1,20 @@
<script lang="ts"> <script lang="ts">
export let val : any; export let val : string;
export let onInput : () => void; export let onInput : () => void = () => {};
export let onBlur: () => void = () => {};
export let onKeypress: (e: KeyboardEvent) => void = (e: KeyboardEvent) => {};
export let doAutofocus: boolean = false;
export let placeholder: string = "";
function init(elem: HTMLInputElement) {
if (doAutofocus) {
elem.focus();
}
}
</script> </script>
<input type="text" bind:value={val} on:input={onInput} size=10/> <input tabindex="1" type="text" placeholder={placeholder} bind:value={val} on:input={onInput} on:blur={onBlur} on:keypress={onKeypress} use:init size=10/>
<!-- <input tabindex="1" type="text" placeholder={placeholder} bind:value={val} on:input={onInput} on:blur={onBlur} on:keypress={()=>{}} use:init size=10/> -->
<style> <style>
input[type=text] { input[type=text] {

View File

@ -5,6 +5,7 @@
export let textArray : Array<string> = []; export let textArray : Array<string> = [];
export let onInput : () => void; export let onInput : () => void;
export let onBlur : () => void = () => {};
function update() { function update() {
@ -23,8 +24,11 @@
}); });
</script> </script>
<!-- <div on:blur={onBlur}> -->
<div> <div>
{#each textArray as inTxt} {#each textArray as inTxt}
<Text bind:val={inTxt} onInput={updateInput}/> <!-- <Text bind:val={inTxt} onInput={updateInput} onBlur={onBlur}/> -->
<!-- <Text bind:val={inTxt} onInput={updateInput} placeholder={"New Item"}/> -->
<Text bind:val={inTxt} onInput={updateInput} onBlur={onBlur} placeholder={"New Item"}/>
{/each} {/each}
</div> </div>

View File

@ -3,7 +3,7 @@
import sunImg from '../../assets/sun-solid.svg'; import sunImg from '../../assets/sun-solid.svg';
import moonImg from '../../assets/moon-solid.svg'; import moonImg from '../../assets/moon-solid.svg';
import { dashApi } from '../../stores/apiStore' import { journalApi } from '../../stores/apiStore'
import type { JournalEntry } from '../../dashclient' import type { JournalEntry } from '../../dashclient'
import { dateUpdate, currentDate } from '../../stores/appStore' import { dateUpdate, currentDate } from '../../stores/appStore'
import * as TxtArr from '../../modules/arrayHelpers'; import * as TxtArr from '../../modules/arrayHelpers';
@ -34,7 +34,7 @@
} }
} }
function prepareJournalEntryForWrite(entry: JournalEntry) { function prepareJournalEntryForWrite(entry: JournalEntry): JournalEntry {
let je = {...entry}; let je = {...entry};
je.thankful = TxtArr.prepareTextArrayForWrite(je.thankful); je.thankful = TxtArr.prepareTextArrayForWrite(je.thankful);
@ -49,7 +49,7 @@
} }
async function fetchJournal() { async function fetchJournal() {
dashApi.getJournalEntryForDate({'date': $currentDate}).then(resp => (initJournalEntry(resp))); journalApi.getJournalEntryForDate({'date': $currentDate}).then(resp => (initJournalEntry(resp)));
} }
onMount(() => { onMount(() => {
@ -61,7 +61,7 @@
clearTimeout(updateTimeout); clearTimeout(updateTimeout);
updateTimeout = setTimeout(function() { updateTimeout = setTimeout(function() {
dashApi.writeJournalEntry({journalEntry: prepareJournalEntryForWrite(journalEntry)}); journalApi.writeJournalEntry({journalEntry: prepareJournalEntryForWrite(journalEntry)});
}, 1000); }, 1000);
} }
</script> </script>
@ -103,22 +103,22 @@
</div> </div>
<style> <style>
.journalTime { /* .journalTime {
width: 100%; width: 100%;
position: relative; position: relative;
} }
*/
.JournalSubcategory { .JournalSubcategory {
width: 90%; width: 90%;
margin: auto; margin: auto;
} }
@media screen and (min-width: 550px) { /* @media screen and (min-width: 550px) {
.journalTime { .journalTime {
width: 550px; width: 550px;
} }
} }
*/
.JournalText { .JournalText {
width: 100%; width: 100%;
} }
@ -130,6 +130,7 @@
box-shadow: 1px 1px 4px grey; box-shadow: 1px 1px 4px grey;
resize: none; resize: none;
columns: 15; columns: 15;
font-size: 16px;
} }
.TimeIcon { .TimeIcon {

View File

@ -0,0 +1,157 @@
<script lang="ts">
import { onMount } from 'svelte';
import shortid from 'shortid';
import sunSolid from '../../assets/sun-solid.svg';
import sunRegular from '../../assets/sun-regular.svg';
import mountainSun from '../../assets/mountain-sun-solid.svg';
import moonSolid from '../../assets/moon-solid.svg';
import type { PlanDay } from '../../dashclient'
import { dateUpdate, currentDate } from '../../stores/appStore'
import { planApi } from '../../stores/apiStore'
import type { PlanItem } from '../../stores/planStore'
import PlanDndList from './PlanDndList.svelte'
import InvertableIcon from '../inputs/InvertableIcon.svelte';
let updateTimeout: NodeJS.Timeout;
interface DayItems {
morning: Array<PlanItem>,
midday: Array<PlanItem>,
afternoon: Array<PlanItem>,
evening: Array<PlanItem>
}
let planDay: PlanDay = {
date: $currentDate,
morning: [],
midday: [],
afternoon: [],
evening: []
};
let planDayItems: DayItems = {
morning: [],
midday: [],
afternoon: [],
evening: []
};
function arrayToItems(arr: Array<string>): Array<PlanItem> {
let items: Array<PlanItem> = [];
if (arr) {
arr.forEach((it) => {
if (it.trim().length != 0) {
items.push({id: shortid.generate(), text:it});
}
})
}
return items;
}
function itemsToArray(items: Array<PlanItem>): Array<string> {
let arr: Array<string> = [];
items.forEach((it) => {
if (it.text.trim().length != 0) {
arr.push(it.text);
}
})
return arr;
}
function initPlanDay(plan: PlanDay) {
console.log(plan);
planDay = plan;
planDayItems = {
morning: arrayToItems(planDay.morning),
midday: arrayToItems(planDay.midday),
afternoon: arrayToItems(planDay.afternoon),
evening: arrayToItems(planDay.evening)
}
}
function preparePlanDayForWrite(items: DayItems): PlanDay {
planDay.morning = itemsToArray(items.morning);
planDay.midday = itemsToArray(items.midday);
planDay.afternoon = itemsToArray(items.afternoon);
planDay.evening = itemsToArray(items.evening);
return planDay;
}
async function fetchPlan() {
planApi.getPlanDayForDate({'date': $currentDate}).then(resp => (initPlanDay(resp)));
}
onMount(() => {
$dateUpdate = fetchPlan;
fetchPlan();
});
function onInput() {
console.log("input");
clearTimeout(updateTimeout);
updateTimeout = setTimeout(function() {
planApi.savePlanForDay({planDay: preparePlanDayForWrite(planDayItems)});
}, 1000);
}
</script>
<div class="plan">
<div class="timeOfDay">
<div class="timeIcon">
<InvertableIcon label="morgens" icon={sunRegular}/>
</div>
<PlanDndList bind:items={planDayItems.morning} onInput={onInput}/>
</div>
<div class="timeOfDay">
<div class="timeIcon">
<InvertableIcon label="mittags" icon={sunSolid}/>
</div>
<PlanDndList bind:items={planDayItems.midday} onInput={onInput}/>
</div>
<div class="timeOfDay">
<div class="timeIcon">
<InvertableIcon label="nachmittags" icon={mountainSun}/>
</div>
<PlanDndList bind:items={planDayItems.afternoon} onInput={onInput}/>
</div>
<div class="timeOfDay">
<div class="timeIcon">
<InvertableIcon label="abends" icon={moonSolid}/>
</div>
<PlanDndList bind:items={planDayItems.evening} onInput={onInput}/>
</div>
</div>
<style>
.plan {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.timeOfDay {
min-width: 130px;
flex-grow: 1;
flex-basis: 0;
}
.timeIcon {
/* position: absolute;
float: left; */
height: 2rem;
width: 2rem;
margin: 0 auto;
margin-bottom: 10px;
margin-top: 5px;
}
</style>

View File

@ -0,0 +1,87 @@
<script lang="ts">
import {dndzone} from 'svelte-dnd-action';
import {flip} from 'svelte/animate';
import type { PlanItem } from '../../stores/planStore'
import PlanInput from './PlanInput.svelte'
import MultiItemTextInput from '../inputs/MultiItemTextInput.svelte'
import Text from '../inputs/InputText.svelte';
import shortid from 'shortid'
export let items: Array<{id: number, text: string}> = [];
export let onInput: () => void;
const flipDurationMs = 200;
function handleSort(e: any) {
let sortedItems: Array<PlanItem> = [];
e.detail.items.forEach((it: PlanItem) => {
if (it.text.trim().length != 0) {
sortedItems.push(it);
}
});
items = sortedItems;
onInput();
}
let newItem: string = "";
function onInputNewItem() {
if (newItem.trim().length != 0) {
items = [...items, {id: shortid.generate(), text: newItem}];
}
newItem = "";
onInput();
}
function onKeypress(e: KeyboardEvent, ) {
if(e.key == "Enter") {
onInputNewItem();
}
}
</script>
<div class="newItemInput">
<Text bind:val={newItem} onInput={onInput} onBlur={onInputNewItem} onKeypress={onKeypress} placeholder={"New Item"}/>
<!-- <MultiItemTextInput bind:textArray={newArray} onInput={onInput} onBlur={onInputNewItem}/> -->
</div>
<section contenteditable="true" use:dndzone={{items, flipDurationMs}} on:consider={handleSort} on:finalize={handleSort}>
<!-- <div class="planItems"> -->
{#each items as item(item.id)}
<div class="planRow" animate:flip={{duration:flipDurationMs}}>
<div class="planInput">
<PlanInput bind:text={item.text} onInput={onInput}/>
</div>
</div>
{/each}
<!-- </div> -->
</section>
<style>
.planItems {
display: flex;
flex-direction: column;
width: 100%;
justify-content: center;
}
.planInput {
width: 80%;
}
.planRow {
/* display: flex; */
width: 100%;
min-height: 1rem;
}
.newItemInput {
width: 90%;
}
</style>

View File

@ -0,0 +1,32 @@
<script lang="ts">
import InputText from '../inputs/InputText.svelte'
export let text: string;
export let onInput: () => void;
export let onBlur: () => void = () => {};
let doEdit: boolean = false;
function onClick() {
doEdit = !doEdit;
}
function handleBlur() {
doEdit = !doEdit;
onBlur();
}
</script>
{#if doEdit}
<InputText bind:val={text} onInput={onInput} onBlur={handleBlur} doAutofocus={true}/>
{:else}
<div class="editableEntry" on:click={onClick}>
<b>{text}</b>
</div>
{/if}
<style>
.editableEntry {
width: 100%;
}
</style>

View File

@ -14,7 +14,9 @@
</script> </script>
<div class="TabBar"> <div class="TabBar">
<DatePicker/> <div class="datePicker">
<DatePicker/>
</div>
<InvertableButton label="Journal" icon={penImg} clickHandler={()=>{clickHandler("Journal")}}/> <InvertableButton label="Journal" icon={penImg} clickHandler={()=>{clickHandler("Journal")}}/>
<InvertableButton label="Plan" icon={calendarImg} clickHandler={()=>{clickHandler("Plan")}}/> <InvertableButton label="Plan" icon={calendarImg} clickHandler={()=>{clickHandler("Plan")}}/>
<InvertableButton label="Tracking" icon={chartImg} clickHandler={()=>{clickHandler("Tracking")}}/> <InvertableButton label="Tracking" icon={chartImg} clickHandler={()=>{clickHandler("Tracking")}}/>
@ -29,8 +31,13 @@
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
/* for horizontal aligning of child divs */ /* for horizontal aligning of child divs */
justify-content: center; /* justify-content: center; */
/* for vertical aligning */ /* for vertical aligning */
align-items: center; align-items: center;
gap: 5px;
}
.datePicker {
margin-right: auto;
} }
</style> </style>

View File

@ -37,7 +37,7 @@ export interface WriteJournalEntryRequest {
/** /**
* *
*/ */
export class DefaultApi extends runtime.BaseAPI { export class JournalApi extends runtime.BaseAPI {
/** /**
*/ */
@ -51,7 +51,7 @@ export class DefaultApi extends runtime.BaseAPI {
const headerParameters: runtime.HTTPHeaders = {}; const headerParameters: runtime.HTTPHeaders = {};
const response = await this.request({ const response = await this.request({
path: `/journal/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(String(requestParameters.date.toISOString().substring(0,10)))), path: `/journal/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(requestParameters.date.toISOString().substring(0,10))),
method: 'DELETE', method: 'DELETE',
headers: headerParameters, headers: headerParameters,
query: queryParameters, query: queryParameters,
@ -78,7 +78,7 @@ export class DefaultApi extends runtime.BaseAPI {
const headerParameters: runtime.HTTPHeaders = {}; const headerParameters: runtime.HTTPHeaders = {};
const response = await this.request({ const response = await this.request({
path: `/journal/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(String(requestParameters.date.toISOString().substring(0,10)))), path: `/journal/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(requestParameters.date.toISOString().substring(0,10))),
method: 'GET', method: 'GET',
headers: headerParameters, headers: headerParameters,
query: queryParameters, query: queryParameters,

View File

@ -0,0 +1,234 @@
/* tslint:disable */
/* eslint-disable */
/**
* Dash API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import * as runtime from '../runtime';
import type {
PlanDay,
PlanMonth,
PlanWeek,
} from '../models';
import {
PlanDayFromJSON,
PlanDayToJSON,
PlanMonthFromJSON,
PlanMonthToJSON,
PlanWeekFromJSON,
PlanWeekToJSON,
} from '../models';
export interface GetPlanDayForDateRequest {
date: Date;
}
export interface GetPlanMonthForDateRequest {
date: Date;
}
export interface GetPlanWeekForDateRequest {
date: Date;
}
export interface SavePlanForDayRequest {
planDay: PlanDay;
}
export interface SavePlanForMonthRequest {
planMonth: PlanMonth;
}
export interface SavePlanForWeekRequest {
planWeek: PlanWeek;
}
/**
*
*/
export class PlanApi extends runtime.BaseAPI {
/**
*/
async getPlanDayForDateRaw(requestParameters: GetPlanDayForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PlanDay>> {
if (requestParameters.date === null || requestParameters.date === undefined) {
throw new runtime.RequiredError('date','Required parameter requestParameters.date was null or undefined when calling getPlanDayForDate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
const response = await this.request({
path: `/plan/day/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(requestParameters.date.toISOString().substring(0,10))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => PlanDayFromJSON(jsonValue));
}
/**
*/
async getPlanDayForDate(requestParameters: GetPlanDayForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PlanDay> {
const response = await this.getPlanDayForDateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async getPlanMonthForDateRaw(requestParameters: GetPlanMonthForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PlanMonth>> {
if (requestParameters.date === null || requestParameters.date === undefined) {
throw new runtime.RequiredError('date','Required parameter requestParameters.date was null or undefined when calling getPlanMonthForDate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
const response = await this.request({
path: `/plan/month/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(requestParameters.date.toISOString().substring(0,10))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => PlanMonthFromJSON(jsonValue));
}
/**
*/
async getPlanMonthForDate(requestParameters: GetPlanMonthForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PlanMonth> {
const response = await this.getPlanMonthForDateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async getPlanWeekForDateRaw(requestParameters: GetPlanWeekForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PlanWeek>> {
if (requestParameters.date === null || requestParameters.date === undefined) {
throw new runtime.RequiredError('date','Required parameter requestParameters.date was null or undefined when calling getPlanWeekForDate.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
const response = await this.request({
path: `/plan/week/entry/{date}`.replace(`{${"date"}}`, encodeURIComponent(requestParameters.date.toISOString().substring(0,10))),
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => PlanWeekFromJSON(jsonValue));
}
/**
*/
async getPlanWeekForDate(requestParameters: GetPlanWeekForDateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PlanWeek> {
const response = await this.getPlanWeekForDateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
*/
async savePlanForDayRaw(requestParameters: SavePlanForDayRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters.planDay === null || requestParameters.planDay === undefined) {
throw new runtime.RequiredError('planDay','Required parameter requestParameters.planDay was null or undefined when calling savePlanForDay.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
const response = await this.request({
path: `/plan/day/entry/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: PlanDayToJSON(requestParameters.planDay),
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async savePlanForDay(requestParameters: SavePlanForDayRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.savePlanForDayRaw(requestParameters, initOverrides);
}
/**
*/
async savePlanForMonthRaw(requestParameters: SavePlanForMonthRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters.planMonth === null || requestParameters.planMonth === undefined) {
throw new runtime.RequiredError('planMonth','Required parameter requestParameters.planMonth was null or undefined when calling savePlanForMonth.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
const response = await this.request({
path: `/plan/month/entry/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: PlanMonthToJSON(requestParameters.planMonth),
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async savePlanForMonth(requestParameters: SavePlanForMonthRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.savePlanForMonthRaw(requestParameters, initOverrides);
}
/**
*/
async savePlanForWeekRaw(requestParameters: SavePlanForWeekRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
if (requestParameters.planWeek === null || requestParameters.planWeek === undefined) {
throw new runtime.RequiredError('planWeek','Required parameter requestParameters.planWeek was null or undefined when calling savePlanForWeek.');
}
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
headerParameters['Content-Type'] = 'application/json';
const response = await this.request({
path: `/plan/week/entry/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
body: PlanWeekToJSON(requestParameters.planWeek),
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
*/
async savePlanForWeek(requestParameters: SavePlanForWeekRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.savePlanForWeekRaw(requestParameters, initOverrides);
}
}

View File

@ -1,3 +1,4 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export * from './DefaultApi'; export * from './JournalApi';
export * from './PlanApi';

View File

@ -0,0 +1,114 @@
/* tslint:disable */
/* eslint-disable */
/**
* Dash API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
*
* @export
* @interface PlanDay
*/
export interface PlanDay {
/**
*
* @type {Date}
* @memberof PlanDay
*/
date: Date;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
morning?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
midday?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
afternoon?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
evening?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
pleasant?: Array<string>;
/**
*
* @type {Array<string>}
* @memberof PlanDay
*/
reminders?: Array<string>;
}
/**
* Check if a given object implements the PlanDay interface.
*/
export function instanceOfPlanDay(value: object): boolean {
let isInstance = true;
isInstance = isInstance && "date" in value;
return isInstance;
}
export function PlanDayFromJSON(json: any): PlanDay {
return PlanDayFromJSONTyped(json, false);
}
export function PlanDayFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlanDay {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'date': (new Date(json['date'])),
'morning': !exists(json, 'morning') ? undefined : json['morning'],
'midday': !exists(json, 'midday') ? undefined : json['midday'],
'afternoon': !exists(json, 'afternoon') ? undefined : json['afternoon'],
'evening': !exists(json, 'evening') ? undefined : json['evening'],
'pleasant': !exists(json, 'pleasant') ? undefined : json['pleasant'],
'reminders': !exists(json, 'reminders') ? undefined : json['reminders'],
};
}
export function PlanDayToJSON(value?: PlanDay | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'date': (value.date.toISOString().substr(0,10)),
'morning': value.morning,
'midday': value.midday,
'afternoon': value.afternoon,
'evening': value.evening,
'pleasant': value.pleasant,
'reminders': value.reminders,
};
}

View File

@ -0,0 +1,74 @@
/* tslint:disable */
/* eslint-disable */
/**
* Dash API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
*
* @export
* @interface PlanMonth
*/
export interface PlanMonth {
/**
*
* @type {Date}
* @memberof PlanMonth
*/
date: Date;
/**
*
* @type {Array<string>}
* @memberof PlanMonth
*/
items?: Array<string>;
}
/**
* Check if a given object implements the PlanMonth interface.
*/
export function instanceOfPlanMonth(value: object): boolean {
let isInstance = true;
isInstance = isInstance && "date" in value;
return isInstance;
}
export function PlanMonthFromJSON(json: any): PlanMonth {
return PlanMonthFromJSONTyped(json, false);
}
export function PlanMonthFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlanMonth {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'date': (new Date(json['date'])),
'items': !exists(json, 'items') ? undefined : json['items'],
};
}
export function PlanMonthToJSON(value?: PlanMonth | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'date': (value.date.toISOString().substr(0,10)),
'items': value.items,
};
}

View File

@ -0,0 +1,81 @@
/* tslint:disable */
/* eslint-disable */
/**
* Dash API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
import type { PlanWeekItem } from './PlanWeekItem';
import {
PlanWeekItemFromJSON,
PlanWeekItemFromJSONTyped,
PlanWeekItemToJSON,
} from './PlanWeekItem';
/**
*
* @export
* @interface PlanWeek
*/
export interface PlanWeek {
/**
*
* @type {Date}
* @memberof PlanWeek
*/
date: Date;
/**
*
* @type {Array<PlanWeekItem>}
* @memberof PlanWeek
*/
items?: Array<PlanWeekItem>;
}
/**
* Check if a given object implements the PlanWeek interface.
*/
export function instanceOfPlanWeek(value: object): boolean {
let isInstance = true;
isInstance = isInstance && "date" in value;
return isInstance;
}
export function PlanWeekFromJSON(json: any): PlanWeek {
return PlanWeekFromJSONTyped(json, false);
}
export function PlanWeekFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlanWeek {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'date': (new Date(json['date'])),
'items': !exists(json, 'items') ? undefined : ((json['items'] as Array<any>).map(PlanWeekItemFromJSON)),
};
}
export function PlanWeekToJSON(value?: PlanWeek | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'date': (value.date.toISOString().substr(0,10)),
'items': value.items === undefined ? undefined : ((value.items as Array<any>).map(PlanWeekItemToJSON)),
};
}

View File

@ -0,0 +1,82 @@
/* tslint:disable */
/* eslint-disable */
/**
* Dash API
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* The version of the OpenAPI document: 0.1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { exists, mapValues } from '../runtime';
/**
*
* @export
* @interface PlanWeekItem
*/
export interface PlanWeekItem {
/**
*
* @type {string}
* @memberof PlanWeekItem
*/
item: string;
/**
*
* @type {number}
* @memberof PlanWeekItem
*/
numTodos?: number;
/**
*
* @type {number}
* @memberof PlanWeekItem
*/
numDone?: number;
}
/**
* Check if a given object implements the PlanWeekItem interface.
*/
export function instanceOfPlanWeekItem(value: object): boolean {
let isInstance = true;
isInstance = isInstance && "item" in value;
return isInstance;
}
export function PlanWeekItemFromJSON(json: any): PlanWeekItem {
return PlanWeekItemFromJSONTyped(json, false);
}
export function PlanWeekItemFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlanWeekItem {
if ((json === undefined) || (json === null)) {
return json;
}
return {
'item': json['item'],
'numTodos': !exists(json, 'numTodos') ? undefined : json['numTodos'],
'numDone': !exists(json, 'numDone') ? undefined : json['numDone'],
};
}
export function PlanWeekItemToJSON(value?: PlanWeekItem | null): any {
if (value === undefined) {
return undefined;
}
if (value === null) {
return null;
}
return {
'item': value.item,
'numTodos': value.numTodos,
'numDone': value.numDone,
};
}

View File

@ -1,3 +1,7 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export * from './JournalEntry'; export * from './JournalEntry';
export * from './PlanDay';
export * from './PlanMonth';
export * from './PlanWeek';
export * from './PlanWeekItem';

View File

@ -1,4 +1,4 @@
import { Configuration, DefaultApi } from "../dashclient"; import { Configuration, JournalApi, PlanApi } from "../dashclient";
console.log(window.location.origin) console.log(window.location.origin)
@ -6,4 +6,5 @@ const configuration = new Configuration({
basePath: "http://192.168.0.181:8080/api/v1", basePath: "http://192.168.0.181:8080/api/v1",
}); });
export const dashApi = new DefaultApi(configuration); export const journalApi = new JournalApi(configuration);
export const planApi = new PlanApi(configuration);

View File

@ -1,6 +1,7 @@
import { writable, readable } from 'svelte/store'; import { writable, readable } from 'svelte/store';
export const curTab = writable("Journal"); // export const curTab = writable("Journal");
export const curTab = writable("Plan");
export const currentDate = writable<Date>(new Date()); export const currentDate = writable<Date>(new Date());

View File

@ -0,0 +1,4 @@
export interface PlanItem {
id: number,
text: string
}