this.handleSave(todo.id, text)} />
42 | )
43 | } else {
44 | element = (
45 |
46 | {
50 | completeTodo(todo.id)
51 | }} />
52 |
55 |
58 | )
59 | }
60 |
61 | return (
62 |
66 | {element}
67 |
68 | )
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/apollo-remote-state/client/src/components/TodoItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 | import classnames from 'classnames'
4 | import TodoTextInput from './TodoTextInput'
5 |
6 | type Props = any;
7 |
8 | export default class TodoItem extends Component {
9 | static propTypes = {
10 | todo: PropTypes.object.isRequired,
11 | editTodo: PropTypes.func.isRequired,
12 | deleteTodo: PropTypes.func.isRequired,
13 | completeTodo: PropTypes.func.isRequired
14 | }
15 |
16 | state = {
17 | editing: false
18 | }
19 |
20 | handleDoubleClick = () => {
21 | this.setState({ editing: true })
22 | }
23 |
24 | handleSave = (id: number, text: string) => {
25 | if (text.length === 0) {
26 | this.props.deleteTodo(id)
27 | } else {
28 | this.props.editTodo(id, text)
29 | }
30 | this.setState({ editing: false })
31 | }
32 |
33 | render() {
34 | const { todo, completeTodo, deleteTodo } = this.props
35 |
36 | let element
37 | if (this.state.editing) {
38 | element = (
39 | this.handleSave(todo.id, text)} />
42 | )
43 | } else {
44 | element = (
45 |
46 | {
50 | completeTodo(todo.id)
51 | }} />
52 |
55 |
58 | )
59 | }
60 |
61 | return (
62 |
66 | {element}
67 |
68 | )
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/apollo-remote-state-no-relay/client/src/components/TodoItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 | import classnames from 'classnames'
4 | import TodoTextInput from './TodoTextInput'
5 |
6 | type Props = any;
7 |
8 | export default class TodoItem extends Component {
9 | static propTypes = {
10 | todo: PropTypes.object.isRequired,
11 | editTodo: PropTypes.func.isRequired,
12 | deleteTodo: PropTypes.func.isRequired,
13 | completeTodo: PropTypes.func.isRequired
14 | }
15 |
16 | state = {
17 | editing: false
18 | }
19 |
20 | handleDoubleClick = () => {
21 | this.setState({ editing: true })
22 | }
23 |
24 | handleSave = (id: number, text: string) => {
25 | if (text.length === 0) {
26 | this.props.deleteTodo(id)
27 | } else {
28 | this.props.editTodo(id, text)
29 | }
30 | this.setState({ editing: false })
31 | }
32 |
33 | render() {
34 | const { todo, completeTodo, deleteTodo } = this.props
35 |
36 | let element
37 | if (this.state.editing) {
38 | element = (
39 | this.handleSave(todo.id, text)} />
42 | )
43 | } else {
44 | element = (
45 |
46 | {
50 | completeTodo(todo.id)
51 | }} />
52 |
55 |
58 | )
59 | }
60 |
61 | return (
62 |
66 | {element}
67 |
68 | )
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/apollo-remote-state-no-relay/server/src/schema.ts:
--------------------------------------------------------------------------------
1 | import { gql } from "apollo-server";
2 |
3 | const typeDefs = gql`
4 | type PageInfo {
5 | hasPreviousPage: Boolean!
6 | hasNextPage: Boolean!
7 | startCursor: String!
8 | endCursor: String!
9 | }
10 |
11 | type Todo {
12 | id: Int!
13 | text: String!
14 | completed: Boolean!
15 | }
16 |
17 | type TodoNotFoundError {
18 | message: String!
19 | }
20 |
21 | union TodoResult = Todo | TodoNotFoundError
22 |
23 | type Query {
24 | todos (
25 | after: String,
26 | before: String,
27 | first: Int,
28 | last: Int
29 | ): [Todo]!
30 |
31 | todo (id: Int!): TodoResult!
32 | }
33 |
34 | type TodoAlreadyCompletedError {
35 | message: String!
36 | }
37 |
38 | union CompleteTodoError = TodoNotFoundError | TodoAlreadyCompletedError
39 |
40 | type CompleteTodoResult {
41 | success: Boolean!
42 | todo: Todo
43 | error: CompleteTodoError
44 | }
45 |
46 | type TodoValidationError {
47 | message: String!
48 | }
49 |
50 | type AddTodoResult {
51 | success: Boolean!
52 | todo: Todo
53 | error: TodoValidationError
54 | }
55 |
56 | type ClearCompletedTodosResult {
57 | success: Boolean!
58 | todos: [Todo]!
59 | }
60 |
61 | type CompleteAllTodosResult {
62 | success: Boolean!
63 | todos: [Todo]!
64 | }
65 |
66 | type DeleteTodoResult {
67 | success: Boolean!
68 | todo: Todo
69 | error: TodoNotFoundError
70 | }
71 |
72 | union EditTodoError = TodoNotFoundError | TodoValidationError
73 |
74 | type EditTodoResult {
75 | success: Boolean!
76 | todo: Todo
77 | error: EditTodoError
78 | }
79 |
80 | type Mutation {
81 | addTodo (text: String!): AddTodoResult!
82 | clearCompletedTodos: ClearCompletedTodosResult!
83 | completeTodo (id: Int!): CompleteTodoResult!
84 | completeAllTodos: CompleteAllTodosResult!
85 | deleteTodo (id: Int!): DeleteTodoResult!
86 | editTodo (id: Int!, text: String!): EditTodoResult!
87 | }
88 | `
89 |
90 | export { typeDefs }
--------------------------------------------------------------------------------
/apollo-remote-state-advanced-cache-apis/client/src/components/TodoItem.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import PropTypes from 'prop-types'
3 | import classnames from 'classnames'
4 | import TodoTextInput from './TodoTextInput'
5 |
6 | type Props = any;
7 |
8 | export default class TodoItem extends Component {
9 | static propTypes = {
10 | todo: PropTypes.object.isRequired,
11 | editTodo: PropTypes.func.isRequired,
12 | deleteTodo: PropTypes.func.isRequired,
13 | completeTodo: PropTypes.func.isRequired
14 | }
15 |
16 | state = {
17 | editing: false
18 | }
19 |
20 | handleDoubleClick = () => {
21 | this.setState({ editing: true })
22 | }
23 |
24 | handleSave = (id: number, text: string) => {
25 | if (text.length === 0) {
26 | this.props.deleteTodo(id)
27 | } else {
28 | this.props.editTodo(id, text)
29 | }
30 | this.setState({ editing: false })
31 | }
32 |
33 | render() {
34 | const { todo, completeTodo, deleteTodo } = this.props
35 |
36 | let element
37 | if (this.state.editing) {
38 | element = (
39 | this.handleSave(todo.id, text)} />
42 | )
43 | } else {
44 | element = (
45 |
46 | {
50 | completeTodo(todo.id)
51 | }} />
52 |
55 |
58 | )
59 | }
60 |
61 | return (
62 |
66 | {element}
67 |
68 | )
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/apollo-remote-state/server/src/shared/utils/paginationUtils.ts:
--------------------------------------------------------------------------------
1 | import { Result } from "../core/result";
2 | import { NumberUtils } from "./numberUtils";
3 |
4 | interface Node {
5 | id: number
6 | }
7 |
8 | type GenericNodeList = Node[];
9 |
10 | export class PaginationUtils {
11 | public static filterByBeforeAndAfter (
12 | items: GenericNodeList,
13 | after?: string,
14 | before?: string,
15 | ) : GenericNodeList {
16 | const isAfterSet = !!after === true;
17 | const isBeforeSet = !!before === true;
18 |
19 | if (isAfterSet) {
20 | const afterIndex = items.findIndex((t) => t.id === Number(after))
21 | const afterIndexFound = afterIndex !== -1;
22 |
23 | if (afterIndexFound) {
24 | items = items.slice(afterIndex + 1)
25 | }
26 | }
27 |
28 | if (isBeforeSet) {
29 | const beforeIndex = items.findIndex((t) => t.id === Number(after))
30 | const beforeIndexFond = beforeIndex !== -1;
31 |
32 | if (beforeIndexFond) {
33 | items = items.slice(0, beforeIndex)
34 | }
35 | }
36 |
37 | return items;
38 | }
39 |
40 | public static limitByFirstAndLast(
41 | items: T[],
42 | first?: number,
43 | last?: number
44 | ): Result {
45 | const isFirstSet = NumberUtils.isANumber(first);
46 | const isLastSet = NumberUtils.isANumber(last);
47 |
48 | if (isFirstSet) {
49 | const isFirstAPositiveNumber = NumberUtils.isANonNegativeNumber(first);
50 |
51 | if (!isFirstAPositiveNumber) {
52 | return Result.fail("First has to be greater than 0");
53 | }
54 |
55 | if (items.length > first) {
56 | return Result.ok(items.slice(0, first));
57 | }
58 | }
59 |
60 | if (isLastSet) {
61 | const isLastAPositiveNumber = NumberUtils.isANonNegativeNumber(last);
62 |
63 | if (!isLastAPositiveNumber) {
64 | return Result.fail("Last has to be greater than 0");
65 | }
66 |
67 | if (items.length > last) {
68 | return Result.ok(items.slice(0, last));
69 | }
70 | }
71 |
72 | return Result.ok(items);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/apollo-remote-state-no-relay/server/src/shared/utils/paginationUtils.ts:
--------------------------------------------------------------------------------
1 | import { Result } from "../core/result";
2 | import { NumberUtils } from "./numberUtils";
3 |
4 | interface Node {
5 | id: number
6 | }
7 |
8 | type GenericNodeList = Node[];
9 |
10 | export class PaginationUtils {
11 | public static filterByBeforeAndAfter (
12 | items: GenericNodeList,
13 | after?: string,
14 | before?: string,
15 | ) : GenericNodeList {
16 | const isAfterSet = !!after === true;
17 | const isBeforeSet = !!before === true;
18 |
19 | if (isAfterSet) {
20 | const afterIndex = items.findIndex((t) => t.id === Number(after))
21 | const afterIndexFound = afterIndex !== -1;
22 |
23 | if (afterIndexFound) {
24 | items = items.slice(afterIndex + 1)
25 | }
26 | }
27 |
28 | if (isBeforeSet) {
29 | const beforeIndex = items.findIndex((t) => t.id === Number(after))
30 | const beforeIndexFond = beforeIndex !== -1;
31 |
32 | if (beforeIndexFond) {
33 | items = items.slice(0, beforeIndex)
34 | }
35 | }
36 |
37 | return items;
38 | }
39 |
40 | public static limitByFirstAndLast(
41 | items: T[],
42 | first?: number,
43 | last?: number
44 | ): Result {
45 | const isFirstSet = NumberUtils.isANumber(first);
46 | const isLastSet = NumberUtils.isANumber(last);
47 |
48 | if (isFirstSet) {
49 | const isFirstAPositiveNumber = NumberUtils.isANonNegativeNumber(first);
50 |
51 | if (!isFirstAPositiveNumber) {
52 | return Result.fail("First has to be greater than 0");
53 | }
54 |
55 | if (items.length > first) {
56 | return Result.ok(items.slice(0, first));
57 | }
58 | }
59 |
60 | if (isLastSet) {
61 | const isLastAPositiveNumber = NumberUtils.isANonNegativeNumber(last);
62 |
63 | if (!isLastAPositiveNumber) {
64 | return Result.fail("Last has to be greater than 0");
65 | }
66 |
67 | if (items.length > last) {
68 | return Result.ok(items.slice(0, last));
69 | }
70 | }
71 |
72 | return Result.ok(items);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/apollo-remote-state-advanced-cache-apis/server/src/shared/utils/paginationUtils.ts:
--------------------------------------------------------------------------------
1 | import { Result } from "../core/result";
2 | import { NumberUtils } from "./numberUtils";
3 |
4 | interface Node {
5 | id: number
6 | }
7 |
8 | type GenericNodeList = Node[];
9 |
10 | export class PaginationUtils {
11 | public static filterByBeforeAndAfter (
12 | items: GenericNodeList,
13 | after?: string,
14 | before?: string,
15 | ) : GenericNodeList {
16 | const isAfterSet = !!after === true;
17 | const isBeforeSet = !!before === true;
18 |
19 | if (isAfterSet) {
20 | const afterIndex = items.findIndex((t) => t.id === Number(after))
21 | const afterIndexFound = afterIndex !== -1;
22 |
23 | if (afterIndexFound) {
24 | items = items.slice(afterIndex + 1)
25 | }
26 | }
27 |
28 | if (isBeforeSet) {
29 | const beforeIndex = items.findIndex((t) => t.id === Number(after))
30 | const beforeIndexFond = beforeIndex !== -1;
31 |
32 | if (beforeIndexFond) {
33 | items = items.slice(0, beforeIndex)
34 | }
35 | }
36 |
37 | return items;
38 | }
39 |
40 | public static limitByFirstAndLast(
41 | items: T[],
42 | first?: number,
43 | last?: number
44 | ): Result {
45 | const isFirstSet = NumberUtils.isANumber(first);
46 | const isLastSet = NumberUtils.isANumber(last);
47 |
48 | if (isFirstSet) {
49 | const isFirstAPositiveNumber = NumberUtils.isANonNegativeNumber(first);
50 |
51 | if (!isFirstAPositiveNumber) {
52 | return Result.fail("First has to be greater than 0");
53 | }
54 |
55 | if (items.length > first) {
56 | return Result.ok(items.slice(0, first));
57 | }
58 | }
59 |
60 | if (isLastSet) {
61 | const isLastAPositiveNumber = NumberUtils.isANonNegativeNumber(last);
62 |
63 | if (!isLastAPositiveNumber) {
64 | return Result.fail("Last has to be greater than 0");
65 | }
66 |
67 | if (items.length > last) {
68 | return Result.ok(items.slice(0, last));
69 | }
70 | }
71 |
72 | return Result.ok(items);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------