elm-graphq: Get list of all objects from connection query - postgresql

I am in deep water.
I am trying to get all rows from a PostgreSQL database through a GraphQL api.
I am using the dillonkearns/elm-graphql elm package.
This is my query (image for context):
query getAllTheDATA {
allEvents1S {
nodes {
name
stopTime
stopDate
startTime
startDate
responsible
}
}
}
Current code:
This code is just to make the query with the selectors.
module Test exposing (..)
import Json.Decode as JD exposing (Decoder)
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet,with)
import Calendar.Object exposing (Events1(..))
import Calendar.Object.Events1 as Events1
import Calendar.Object.Events1SConnection as EConn
import Calendar.Query as Query
import Calendar.Scalar exposing (Id(..))
import Calendar.Interface
import Calendar.Interface
type alias Activity2 =
{ name : Maybe String -- The name of each activity
, start_date : Maybe String -- The start date for an activity
, start_time: Maybe String -- The start time for an activity
, stop_date : Maybe String -- The end date for an activity
, stop_time: Maybe String -- The end time for an activity
, responsible : Maybe String -- who is responsible
}
eventsListSelection : SelectionSet (List Activity2) Calendar.Object.Events1SConnection
eventsListSelection =
EConn.nodes <----- this is where the problem lies
fetchEventsQuery : SelectionSet (Maybe (List Activity2)) RootQuery
fetchEventsQuery =
Query.allEvents1S (List Activity2) eventsListSelection
Questions:
How would I, in elm using the elm-graphql package, collect this data and store it in a list?

import Browser
import Calendar.Object.Events1 as Events1Object
import Calendar.Object.Events1SConnection as Events1SConnection
import Calendar.Query as Query
import Graphql.Operation exposing (RootQuery)
import Graphql.SelectionSet as SelectionSet exposing (SelectionSet)
import Html exposing (Html, div, text)
-- MAIN
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
-- MODEL
type alias Model =
{ events : Status (List Event) }
type Status a
= Failure
| Loading
| Success a
type alias Event =
{ name : String
, startDate : String
, startTime: String
, stopDate : String
, stopTime: String
, responsible : String
}
-- INIT
init : () -> ( Model, Cmd Msg )
init _ =
( Model Loading
, Graphql.Http.send GotEvents (Graphql.Http.queryRequest "https://graphql-calendar.example.com/" query)
)
-- UPDATE
type Msg
= GotEvents (Result (Error (List Event)) List Event)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GotEvents result ->
case result of
Err _ ->
( { model | events = Failure }
, Cmd.none
)
Ok events ->
( { model | events = Success events }
, Cmd.none
)
-- VIEW
view : Model -> Html Msg
view model =
case model.events of
Success events ->
div []
[ List.map viewEvent events ]
Loading ->
div []
[ text "Loading" ]
Failure ->
div []
[ text "Failure" ]
viewEvent : Event -> Html Msg
viewEvent event =
div []
[ text event.name ]
-- GRAPHQL
query : SelectionSet (List Event) RootQuery
query =
Query.allEvents1s
(Events1SConnection.nodes
(SelectionSet.map6 Event
Events1Object.name
Events1Object.startDate
Events1Object.startTime
Events1Object.stopDate
Events1Object.stopTime
Events1Object.responsible
)
)
|> SelectionSet.nonNullOrFail
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none

Related

Middleware to add time to all actions

Using Redux Toolkit, I have many action creators that have prepare callbacks adding a unixtime property to the payload. This property gets the Date.now() value. Since I'm continually adding more actions requiring a time, I'm thinking I'll instead add middleware like the following:
import { Middleware } from 'redux';
import { RootState } from '../sliceReducer'; // type of my app's Redux state
const unixtimeMiddleware: Middleware<{}, RootState> = () => (next) => (action) => {
if (action && !action.meta) {
action.meta = {};
}
action.meta.unixtime = Date.now();
return next(action);
};
export default unixtimeMiddleware;
My question is:
Is this the right type for the middleware?
Possibly related to (1), is there a way to automatically have meta: { unixtime: number } added to all RTK action types, or do I need to create types that extend the built-in action types like:
import { PayloadAction } from '#reduxjs/toolkit';
/**
* An extension of Redux Toolkit's PayloadAction which includes a .meta.unixtime property.
*
* #template P The type of the action's payload.
* #template M Union to the action's base meta type { unixtime: number } (optional)
* #template E The type of the action's error (optional)
*
* #public
*/
export type PayloadActionUnixtime<P, M = never, E = never> = PayloadAction<
P,
string,
{ unixtime: number } & ([M] extends [never] ? {} : M),
E
>;
(Side note: I chose the name unixtime over something like timestamp to reduce the likelihood someone would think it is a string like YYYY-MM-DD HH-MM-SS)

Custom procedure fails to collect properties of a class parameter; why?

OK, first of all, I'm a rookie with Caché, so the code will probably be poor, but...
I need to be able to query the Caché database in Java in order to rebuild source files out of the Studio.
I can dump methods etc without trouble, however there is one thing which escapes me... For some reason, I cannot dump the properties of parameter EXTENTQUERYSPEC from class Samples.Person (namespace: SAMPLES).
The class reads like this in Studio:
Class Sample.Person Extends (%Persistent, %Populate, %XML.Adaptor)
{
Parameter EXTENTQUERYSPEC = "Name,SSN,Home.City,Home.State";
// etc etc
}
Here is the code of the procedure:
CREATE PROCEDURE CacheQc.getParamDesc(
IN className VARCHAR(50),
IN methodName VARCHAR(50),
OUT description VARCHAR(8192),
OUT type VARCHAR(50),
OUT defaultValue VARCHAR(1024)
) RETURNS NUMBER LANGUAGE COS {
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
And the Java code:
private void getParamDetail(final String className, final String paramName)
throws SQLException
{
final String call
= "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?) }";
try (
final CallableStatement statement = connection.prepareCall(call);
) {
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, className);
statement.setString(3, paramName);
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
final int ret = statement.getInt(1);
// HERE
if (ret != 0)
throw new SQLException("failed to read parameter");
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
Now, for the aforementioned class/parameter pair the condition marked // HERE is always triggered and therefore the exception thrown... If I comment the whole line then I see that all three of OUT parameters are null, even defaultValue!
I'd have expected the latter to have the value mentioned in Studio...
So, why does this happen? Is my procedure broken somewhat?
In first you should check that you send right value for className and paramName, full name and in right case and. Why you choose storage procedures, when you can use select? And you can call your procedure in System Management Portal to see about probable errors.
select description, type,_Default "Default" from %Dictionary.ParameterDefinition where id='Sample.Person||EXTENTQUERYSPEC'
Your example, works well for me.
package javaapplication3;
import com.intersys.jdbc.CacheDataSource;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class JavaApplication3 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws SQLException {
CacheDataSource ds = new CacheDataSource();
ds.setURL("jdbc:Cache://127.0.0.1:56775/Samples");
ds.setUser("_system");
ds.setPassword("SYS");
Connection dbconnection = ds.getConnection();
String call = "{ ? = call CacheQc.getParamDesc(?, ?, ?, ?, ?)}";
CallableStatement statement = dbconnection.prepareCall(call);
statement.registerOutParameter(1, Types.INTEGER);
statement.setString(2, "Sample.Person");
statement.setString(3, "EXTENTQUERYSPEC");
statement.registerOutParameter(4, Types.VARCHAR);
statement.registerOutParameter(5, Types.VARCHAR);
statement.registerOutParameter(6, Types.VARCHAR);
statement.executeUpdate();
int ret = statement.getInt(1);
System.out.println("ret = " + ret);
System.out.println(" description: " + statement.getString(4));
System.out.println(" type : " + statement.getString(5));
System.out.println(" default : " + statement.getString(6));
}
}
end result
ret = 0
description: null
type : null
default : Name,SSN,Home.City,Home.State
UPD:
try to change code of your procedure and add some debug like here
Class CacheQc.procgetParamDesc Extends %Library.RegisteredObject [ ClassType = "", DdlAllowed, Owner = {UnknownUser}, Not ProcedureBlock ]
{
ClassMethod getParamDesc(className As %Library.String(MAXLEN=50), methodName As %Library.String(MAXLEN=50), Output description As %Library.String(MAXLEN=8192), Output type As %Library.String(MAXLEN=50), Output defaultValue As %Library.String(MAXLEN=1024)) As %Library.Numeric(SCALE=0) [ SqlName = getParamDesc, SqlProc ]
{
set ref = className _ "||" _ methodName
set row = ##class(%Dictionary.ParameterDefinition).%OpenId(ref)
set ^debug($i(^debug))=$lb(ref,row,$system.Status.GetErrorText($g(%objlasterror)))
if (row = "") {
quit 1
}
set description = row.Description
set type = row.Type
set defaultValue = row.Default
quit 0
}
}
and after some test from java, check zw ^debug
SAMPLES>zw ^debug
^debug=4
^debug(3)=$lb("Sample.Person||EXTENTQUERYSPEC","31#%Dictionary.ParameterDefinition","ERROR #00: (no error description)")
Well, uh, I found the problem... Talk about stupid.
It happens that I had the Samples.Person class open in Studio and had made a "modification" to it; and deleted it just afterwards. Therefore the file was "as new"...
But the procedure doesn't seem to agree with this statement.
I closed the Studio where that file was, selected not to modify the "changes", reran the procedure again, and it worked...
Strangely enough, the SQL query worked even with my "fake modification". I guess it's a matter of some cache problem...

Spinejs routing not saving state

I'm trying to get states into my spine application. On click, an item is added to a list. An url is then created and navigated to, and then the list get's rendered. However, when I use the browsers "back" functionality, the list doesn't change back to the previous state. How to get this to work?
This is the relevant code, I left out what seemed irrelevant, but if more is required I'll provided it.
class App extends Spine.Controller
constructor: ->
super
#products = new Products
#filters = new Filters
Filter.bind 'filterAdded', => #navigateAfterFilterChange()
Filter.bind 'filterRemoved', => #navigateAfterFilterChange()
Spine.Route.setup( history: false )
renderAll: ->
#products.render()
#filters.render()
navigateAfterFilterChange: ->
Spine.Route.navigate( encodeURIComponent( JSON.stringify( _.map( Filter.active_filters, ( filter ) -> { t: filters.type, v: filters.value } ) ) ) )
class Filter extends Spine.Model
listen: => #This is used to make the right list item listen to a click event
$("'a[data-cid=\"#{ #id }\"]'").one 'click', #triggerFilter
triggerFilter: (e) =>
e.preventDefault()
filter = Filter.find( $( e.currentTarget ).attr( 'data-cid' ) )
if #active
#active = false
Filter.active_filters = _.reject Filter.active_filters, (x) -> ( x.type is filter.type and x.value is filter.value )
#save()
Filter.trigger 'filterRemoved', #
else
#active = true
Filter.active_filters.push filter
#save()
Filter.trigger 'filterAdded', #
class Filters extends Spine.Controller
constructor: ->
super
#utils = new GeneralScripts
#createFilters()
#listenForTypeActivation()
#routes
"": ( params ) ->
#render()
"*glob": ( params ) ->
#render()
Not sure, but looks like you may need to send params with render()
class Filters extends Spine.Controller
constructor: ->
super
#utils = new GeneralScripts
#createFilters()
#listenForTypeActivation()
#routes
"": ( params ) ->
#render(params)
"*glob": ( params ) ->
#render(params)
you would also need to handle params in the render method of course

How to create read-only field in View

I have a form with 2 fields - empno and name. Both fill up with default value. When display in view, I want empno is read-only and name is editable.
In view creation, I am using #leaveform.value.get.empno to display ready-only and work fine. The problem only occur during insert with error ([NoSuchElementException: None.get]).
Questions:
The problem is return error does not have value property. What else could I use to get the value?
Could I skip #inputText for read-only field?
Refer below my code:
// ***** CONTROLLER *****//
val leaveform = Form[LeaveModel](
mapping(
"empno" -> nonEmptyText,
"name" -> nonEmptyText
)((no, empno) => LeaveModel(empno, name))
((leave: LeaveModel) => Some(leave.empno, leave.name))
)
def create = withAuth { username => implicit request =>
// Define default values
val empno = "STUDENT"
val name = ""
// Set default values
val filledForm = leaveform.fill(LeaveModel(empno,name))
Ok(html.leave.form(filledForm))
}
def insert = Action (
implicit request => {
leaveform.bindFromRequest.fold(
error => {
BadRequest(html.leave.form(error)) // Question 1. Here is the error.
},
leave => {
LeaveModel.insert(leave)
Redirect(routes.indexController.index())
}
)
}
)
// ***** VIEW START***** //
#(leaveform: Form[LeaveModel])
#leaveform.value.get.empno
#helper.form(
action = (routes.LeaveController.update(oid)),
'id -> "leaveform") {
#inputText(leaveform("empno")) // Question 2.
#inputText(leaveform("name"))
}
It is not mandatory to use the form helpers. If you use them you can pass the attribute readonly or style the field with CSS to make it look read only.
Twitter bootstrap disabled by CSS:
#inputText(
editForm("createdOn"),
'id -> "createdOn",
'class -> "input-xlarge disabled",
'_label -> Messages("createdOn"),
'_help -> ""
)
Pass optional attribute: readonly
#inputText(
editForm("createdOn"),
'id -> "createdOn",
'class -> "input-xlarge",
'_label -> Messages("createdOn"),
'readonly -> "readonly",
'_help -> " This is read only"
)
You can also don't resend the field, but display its value:
<span class="date">Created on: #editForm("createdOn").value</span>
Update 2018-01-24
Play field is now returning a Optional, see the docs. This means you can get the value from the field like:
#form("fieldName").getValue.get (can throw a NPE)
#form("fieldName").getValue.getOrElse("defaultValue")
Try using the Flash context when returning a form to the user:
def create = withAuth { username => implicit request =>
// leaveForm initialization as before
// use form data from flash if present
val form = if (flash.get("error").isDefined)
leaveForm.bind(flash.data)
else
leaveForm
Ok(stakeholders.register(form))
}
def insert = Action { implicit request =>
leaveForm.bindFromRequest.fold(
hasErrors = { form =>
Redirect(routes.Leaves.create). // put correct route here
flashing(Flash(form.data) +
("error" -> Messages("validation.errors"))) // customize error message
},
leave => {
LeaveModel.insert(leave)
Redirect(routes.indexController.index())
}
)
}
HTH, Erich

flash_as3_facebook_api: how to iterate over FacebookSession object that is returned by FacebookDesktop.login

in flashbuilder debugger mode, I can examine all the props/vals of the FacebookSession object returned by FacebookDesktop.login when I place a breakpoint in my loginhandler method.
however, I cannot seem to iterate through the FacebookSession object using for...in. I have checked to see if the FacebookSession is dynamic using ObjectUtil.isDynamicObject(...), but it is not, so a for..in should work.
public function gf_handle_facebook_login_return( argl_success : Object ,
argl_failure : Object ) : void
{ // IF I ADD breakpoint here, I get a fully populated argl_success object in flashbuilder's Debugger Variables tab.
trace( "gf_handle_facebook_login_return , A : " + typeof( argl_success ) + " , " + argl_success[ "uid" ] ) ; // works
trace( "gf_handle_facebook_login_return , C : " + ObjectUtil.isDynamicObject( argl_success ) ) ; // false ... is NOT a dynamic class
var lvo_FBS : FacebookSession = FacebookSession ( argl_success ) ; // tried it with and without casting
var lvn_prop :* ;
for ( lvn_prop in lvo_FBS)
{ trace( "gf_handle_facebook_login_return , D : " + lvn_prop ) ; // is never called
}
for each( lvn_prop in lvo_FBS)
{ trace( "gf_handle_facebook_login_return , E : " + lvn_prop ) ; // is never called
}
}
For in will only loop through dynamic properties and as you said it is not a dynamic.
Try this example
//Get an XML description of this class
//and return the variable types as XMLList with e4x
var varList:XMLList = flash.utils.describeType(myVO)..variable;
for(var i:int; i < varList.length(); i++){
//Show the name and the value
trace(varList[i].#name+':'+ myVO[varList[i].#name]);
}