Merge pull request #7 from StevanFreeborn/stevanfreeborn/feat/add-rust-sdk-and-examples

feat: add rust sdk examples
This commit is contained in:
Stevan Freeborn
2026-03-26 21:56:17 -05:00
committed by GitHub
38 changed files with 10084 additions and 6406 deletions
+1
View File
@@ -0,0 +1 @@
next-env.d.ts
+44
View File
@@ -0,0 +1,44 @@
import nextPlugin from '@next/eslint-plugin-next';
import prettierPlugin from 'eslint-plugin-prettier';
import prettierConfig from 'eslint-config-prettier';
import tsParser from '@typescript-eslint/parser';
import tsPlugin from '@typescript-eslint/eslint-plugin';
export default [
{
ignores: [
'.next/**',
'node_modules/**',
'coverage/**',
'.swc/**',
],
},
{
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
'@next/next': nextPlugin,
'@typescript-eslint': tsPlugin,
prettier: prettierPlugin,
},
rules: {
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
...tsPlugin.configs.recommended.rules,
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
},
},
prettierConfig,
];
+3 -2
View File
@@ -1,10 +1,11 @@
import nextJest from 'next/jest'; import type { Config } from 'jest';
import nextJest from 'next/jest.js';
const createJestConfig = nextJest({ const createJestConfig = nextJest({
dir: './', dir: './',
}); });
const config = { const config: Config = {
testEnvironment: 'jest-environment-jsdom', testEnvironment: 'jest-environment-jsdom',
clearMocks: true, clearMocks: true,
collectCoverage: true, collectCoverage: true,
+1 -5
View File
@@ -1,8 +1,4 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {};
experimental: {
appDir: true,
},
};
module.exports = nextConfig; module.exports = nextConfig;
+9412 -6335
View File
File diff suppressed because it is too large Load Diff
+25 -22
View File
@@ -6,33 +6,36 @@
"dev": "cross-env NODE_OPTIONS='--inspect' next dev", "dev": "cross-env NODE_OPTIONS='--inspect' next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "eslint .",
"test": "jest", "test": "jest",
"test-coverage": "jest && live-server coverage/" "test-coverage": "jest && live-server coverage/"
}, },
"dependencies": { "dependencies": {
"@markdoc/markdoc": "^0.2.2", "@markdoc/markdoc": "^0.5.7",
"@types/node": "18.15.11", "@types/node": "25.5.0",
"@types/react": "18.0.33", "@types/react": "19.2.14",
"@types/react-dom": "18.0.11", "@types/react-dom": "19.2.3",
"@vercel/analytics": "^1.0.0", "@vercel/analytics": "^2.0.1",
"eslint": "8.38.0", "eslint": "10.1.0",
"eslint-config-next": "13.3.0", "eslint-config-next": "16.2.1",
"next": "13.2.4", "next": "16.2.1",
"prismjs": "^1.29.0", "prismjs": "^1.30.0",
"react": "18.2.0", "react": "19.2.4",
"react-dom": "18.2.0", "react-dom": "19.2.4",
"typescript": "5.0.4" "typescript": "6.0.2"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^5.16.5", "@eslint/eslintrc": "^3.3.5",
"@testing-library/react": "^14.0.0", "@testing-library/dom": "^10.4.1",
"@types/prismjs": "^1.26.0", "@testing-library/jest-dom": "^6.9.1",
"cross-env": "^7.0.3", "@testing-library/react": "^16.3.2",
"eslint-plugin-prettier": "^4.2.1", "@types/prismjs": "^1.26.6",
"jest": "^29.5.0", "cross-env": "^10.1.0",
"jest-environment-jsdom": "^29.5.0", "eslint-config-prettier": "^10.1.8",
"prettier": "^2.8.7", "eslint-plugin-prettier": "^5.5.5",
"ts-node": "^10.9.1" "jest": "^30.3.0",
"jest-environment-jsdom": "^30.3.0",
"prettier": "^3.8.1",
"ts-node": "^10.9.2"
} }
} }
File diff suppressed because one or more lines are too long
+33 -23
View File
@@ -2,13 +2,24 @@
import React, { import React, {
Children, Children,
MouseEvent,
ReactElement, ReactElement,
ReactNode, ReactNode,
useState, useState,
} from 'react'; } from 'react';
import styles from './CodeSnippet.module.css'; import styles from './CodeSnippet.module.css';
interface MarkdocFenceProps {
language?: string;
content?: string;
className?: string;
}
function isMarkdocElement(
child: ReactNode
): child is ReactElement<MarkdocFenceProps> {
return React.isValidElement(child);
}
function CodeSnippetCopyButton({ function CodeSnippetCopyButton({
copyText, copyText,
}: { }: {
@@ -20,7 +31,7 @@ function CodeSnippetCopyButton({
const [showTooltip, setShowTooltip] = const [showTooltip, setShowTooltip] =
useState<boolean>(false); useState<boolean>(false);
const handleCopy = (e: MouseEvent<HTMLButtonElement>) => { const handleCopy = () => {
setCopyButtonTooltip(true); setCopyButtonTooltip(true);
setTimeout(() => { setTimeout(() => {
setCopyButtonTooltip(false); setCopyButtonTooltip(false);
@@ -129,30 +140,29 @@ export default function CodeSnippet({
setSelectedLanguage(e.target.value); setSelectedLanguage(e.target.value);
}; };
const code = Children.toArray(children) const childrenArray = Children.toArray(children);
.filter(
child =>
React.isValidElement(child) &&
child.props.className ===
`language-${selectedLanguage}`
)
.map(child => {
return child as ReactElement;
})[0];
const snippetLanguages = Children.toArray(children).map( const code = childrenArray.find(
child => { (child): child is ReactElement<MarkdocFenceProps> => {
if (React.isValidElement(child)) { if (!isMarkdocElement(child)) return false;
const languageClassParts = const { language, className } = child.props;
child.props.className.split('-'); return (
if (languageClassParts.length > 1) { language === selectedLanguage ||
const language = languageClassParts[1]; className === `language-${selectedLanguage}`
return language; );
}
}
} }
); );
const snippetLanguages = childrenArray
.map(child => {
if (isMarkdocElement(child)) {
const { language, className } = child.props;
return language || className?.split('-')[1];
}
return undefined;
})
.filter((l): l is string => typeof l === 'string');
return ( return (
<div className={styles.snippetContainer}> <div className={styles.snippetContainer}>
<div className={styles.snippetHeader}> <div className={styles.snippetHeader}>
@@ -176,7 +186,7 @@ export default function CodeSnippet({
</> </>
) : null} ) : null}
<CodeSnippetCopyButton <CodeSnippetCopyButton
copyText={code.props.content} copyText={code?.props.content ?? ''}
/> />
</div> </div>
</div> </div>
+1
View File
@@ -3,6 +3,7 @@ import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-csharp'; import 'prismjs/components/prism-csharp';
import 'prismjs/components/prism-json'; import 'prismjs/components/prism-json';
import 'prismjs/components/prism-python'; import 'prismjs/components/prism-python';
import 'prismjs/components/prism-rust';
import './prism-custom.css'; import './prism-custom.css';
export default function Fence({ export default function Fence({
+4 -1
View File
@@ -1,3 +1,4 @@
import { ChangeEvent } from 'react';
import { useSectionContext } from '../context/section'; import { useSectionContext } from '../context/section';
import { Doc, DocsStructure } from '../types/types'; import { Doc, DocsStructure } from '../types/types';
import { toKebabCase } from '../utils/stringUtils'; import { toKebabCase } from '../utils/stringUtils';
@@ -9,7 +10,9 @@ export default function SectionDropdown({
version: DocsStructure; version: DocsStructure;
}) { }) {
const { section, setSection } = useSectionContext(); const { section, setSection } = useSectionContext();
const handleSelectChange = (e: any) => { const handleSelectChange = (
e: ChangeEvent<HTMLSelectElement>
) => {
setSection(e.target.value); setSection(e.target.value);
location.hash = e.target.value; location.hash = e.target.value;
}; };
+17 -3
View File
@@ -7,7 +7,14 @@ import {
useState, useState,
} from 'react'; } from 'react';
const SectionContext = createContext({}); type SectionContextType = {
section: string;
setSection: (section: string) => void;
};
const SectionContext = createContext<
SectionContextType | undefined
>(undefined);
export const SectionContextProvider = ({ export const SectionContextProvider = ({
children, children,
@@ -25,5 +32,12 @@ export const SectionContextProvider = ({
); );
}; };
export const useSectionContext: any = () => export const useSectionContext = (): SectionContextType => {
useContext(SectionContext); const context = useContext(SectionContext);
if (!context) {
throw new Error(
'useSectionContext must be used within SectionContextProvider'
);
}
return context;
};
+17 -3
View File
@@ -7,6 +7,11 @@ import {
useState, useState,
} from 'react'; } from 'react';
interface ThemeContextType {
theme: string;
setTheme: (theme: string) => void;
}
const darkTheme = { const darkTheme = {
color: 'white', color: 'white',
backgroundColor: '#05254a', backgroundColor: '#05254a',
@@ -17,7 +22,9 @@ const lightTheme = {
backgroundColor: 'white', backgroundColor: 'white',
}; };
const ThemeContext = createContext({}); const ThemeContext = createContext<
ThemeContextType | undefined
>(undefined);
export const ThemeContextProvider = ({ export const ThemeContextProvider = ({
children, children,
@@ -38,5 +45,12 @@ export const themes = {
light: lightTheme, light: lightTheme,
} as { [key: string]: { [key: string]: string } }; } as { [key: string]: { [key: string]: string } };
export const useThemeContext: any = () => export const useThemeContext = (): ThemeContextType => {
useContext(ThemeContext); const context = useContext(ThemeContext);
if (!context) {
throw new Error(
'useThemeContext must be used within ThemeContextProvider'
);
}
return context;
};
+2
View File
@@ -9,6 +9,8 @@ export default function GlobalError({
error: Error; error: Error;
reset: () => void; reset: () => void;
}) { }) {
console.error(error);
return ( return (
<div className={styles.container}> <div className={styles.container}>
<h2>Something went wrong!</h2> <h2>Something went wrong!</h2>
+3 -2
View File
@@ -15,11 +15,12 @@ export const metadata = {
}, },
], ],
}, },
viewport: { };
export const viewport = {
width: 'device-width', width: 'device-width',
initialScale: 1, initialScale: 1,
maximumScale: 1, maximumScale: 1,
},
}; };
export default function RootLayout({ export default function RootLayout({
+15 -3
View File
@@ -83,7 +83,7 @@ function parseMarkdown(sourcePath: string): ReactNode {
const ast = Markdoc.parse(source); const ast = Markdoc.parse(source);
const content = Markdoc.transform( const content = Markdoc.transform(
ast, ast,
markDocConfig as any markDocConfig as never
); );
const children = Markdoc.renderers.react(content, React, { const children = Markdoc.renderers.react(content, React, {
components: { components: {
@@ -102,7 +102,13 @@ function getCopyChild(
docPath: string docPath: string
) { ) {
const copyPath = getCopyPath(version, doc, docPath); const copyPath = getCopyPath(version, doc, docPath);
return parseMarkdown(copyPath); const child = parseMarkdown(copyPath);
if (React.isValidElement(child)) {
return React.cloneElement(child, { key: 'copy' });
}
return child;
} }
function getExampleChild( function getExampleChild(
@@ -111,7 +117,13 @@ function getExampleChild(
docPath: string docPath: string
) { ) {
const examplePath = getExamplePath(version, doc, docPath); const examplePath = getExamplePath(version, doc, docPath);
return parseMarkdown(examplePath); const child = parseMarkdown(examplePath);
if (React.isValidElement(child)) {
return React.cloneElement(child, { key: 'example' });
}
return child;
} }
export function loadSections( export function loadSections(
@@ -56,6 +56,23 @@ print(f'Name: {response.data.app.name}')
print(f'href: {response.data.app.href}') print(f'href: {response.data.app.href}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let app = client.get_app(195).await?;
println!(
"{}, {}",
app.id,
app.name.unwrap_or_default()
);
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -66,6 +66,30 @@ for app in response.data.apps:
print(f'href: {app.href}') print(f'href: {app.href}')
``` ```
```rust
use onspring::{OnspringClient, PagingRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let paging = PagingRequest {
page_number: 1,
page_size: 10,
};
let response = client.list_apps(Some(paging)).await?;
for app in response.items.unwrap_or_default() {
println!(
"{}, {}",
app.id,
app.name.unwrap_or_default()
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -67,6 +67,26 @@ for app in response.data.apps:
print(f'href: {app.href}') print(f'href: {app.href}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let ids = vec![8, 79, 137, 193, 183];
let response = client.batch_get_apps(&ids).await?;
for app in response.items.unwrap_or_default() {
println!(
"{}, {}",
app.id,
app.name.unwrap_or_default()
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -56,4 +56,16 @@ else:
print('Attempt to connect failed') print('Attempt to connect failed')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
client.ping().await?;
println!("Connected to the Onspring API successfully.");
```
{% /code %} {% /code %}
@@ -54,6 +54,19 @@ print(f'Status Code: {response.statusCode}')
print(f'Field Id: {response.data.id}') print(f'Field Id: {response.data.id}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let field = client.get_field(6986).await?;
println!("Field Id: {}", field.id);
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -64,6 +64,26 @@ for field in response.data.fields:
print(f'Field Id: {field.id}') print(f'Field Id: {field.id}')
``` ```
```rust
use onspring::{OnspringClient, PagingRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let paging = PagingRequest {
page_number: 1,
page_size: 10,
};
let response = client.list_fields(195, Some(paging)).await?;
for field in response.items.unwrap_or_default() {
println!("Field Id: {}", field.id);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -63,6 +63,22 @@ for field in response.data.fields:
print(f'Field Id: {field.id}') print(f'Field Id: {field.id}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let ids = vec![6983, 6986, 6987, 6985, 6984];
let response = client.batch_get_fields(&ids).await?;
for field in response.items.unwrap_or_default() {
println!("Field Id: {}", field.id);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -96,6 +96,31 @@ print(f'Status Code: {response.statusCode}')
print(f'File Id: {response.data.id}') print(f'File Id: {response.data.id}')
``` ```
```rust
use onspring::{OnspringClient, SaveFileRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let request = SaveFileRequest {
record_id: 140,
field_id: 6989,
notes: Some(
"Updating record with attachment.".to_string()
),
modified_date: Some(chrono::Utc::now()),
file_name: "test-attachment.txt".to_string(),
file_data: std::fs::read("test-attachment.txt")?,
content_type: "text/plain".to_string(),
};
let response = client.upload_file(request).await?;
println!("New File Id is: {}", response.id);
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -60,4 +60,17 @@ else:
print('Error deleting file') print('Error deleting file')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
client.delete_file(140, 6989, 1904).await?;
println!("File deleted successfully");
```
{% /code %} {% /code %}
@@ -76,6 +76,25 @@ with open(filePath, "wb") as file:
print(f'File Location: {filePath}') print(f'File Location: {filePath}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let file = client
.get_file(1, 6989, 89)
.await?;
println!("File Name: {:?}", file.file_name);
println!("Content Type: {:?}", file.content_type);
println!("Size: {} bytes", file.data.len());
std::fs::write(&file.file_name, &file.data)?;
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="text" %} {% code heading="RESPONSE" defaultLanguage="text" %}
@@ -53,6 +53,22 @@ print(f'Name: {response.data.fileInfo.name}')
print(f'Content Type: {response.data.fileInfo.contentType}') print(f'Content Type: {response.data.fileInfo.contentType}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let info = client
.get_file_info(1, 6989, 89)
.await?;
println!("Name: {:?}", info.name);
println!("Content Type: {:?}", info.content_type);
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -67,4 +67,22 @@ print(f'Status Code: {response.statusCode}')
print(f'Message: {response.message}') print(f'Message: {response.message}')
``` ```
```rust
use onspring::OnspringClient;
use uuid::Uuid;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let item_id = Uuid::parse_str(
"e3371dbf-b557-4a31-b32f-33c0265d2a59"
)?;
client.delete_list_item(906, item_id).await?;
println!("List item deleted");
```
{% /code %} {% /code %}
@@ -89,6 +89,28 @@ print(f'Status Code: {response.statusCode}')
print(f'Id: {response.data.id}') print(f'Id: {response.data.id}')
``` ```
```rust
use onspring::{OnspringClient, SaveListItemRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let request = SaveListItemRequest {
id: None,
name: "Not Started".to_string(),
numeric_value: Some(0.0),
color: Some("#ffffff".to_string()),
};
let response = client
.save_list_item(906, request)
.await?;
println!("Id: {}", response.id);
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -58,4 +58,17 @@ print(f'Status Code: {response.statusCode}')
print(f'Message: {response.message}') print(f'Message: {response.message}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
client.delete_record(195, 140).await?;
println!("Record deleted");
```
{% /code %} {% /code %}
@@ -73,4 +73,22 @@ print(f'Status Code: {response.statusCode}')
print(f'Message: {response.message}') print(f'Message: {response.message}')
``` ```
```rust
use onspring::{OnspringClient, BatchDeleteRecordsRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let request = BatchDeleteRecordsRequest {
app_id: 195,
record_ids: vec![138, 139],
};
client.batch_delete_records(request).await?;
println!("Records deleted successfully");
```
{% /code %} {% /code %}
@@ -70,6 +70,36 @@ for field in response.data.fields:
print(f'Value: {field.GetResultValueString()}') print(f'Value: {field.GetResultValueString()}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let record = client
.get_record(195, 1, None, None)
.await?;
println!(
"AppId: {}, RecordId: {}",
record.app_id,
record.record_id
);
if let Some(field_data) = record.field_data {
for field in field_data {
println!(
"FieldId: {}, Type: {:?}, Value: {}",
field.field_id,
field.value_type,
field.value
);
}
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -71,6 +71,32 @@ for record in response.data.records:
print(f'Value: {field.GetResultValueString()}') print(f'Value: {field.GetResultValueString()}')
``` ```
```rust
use onspring::{OnspringClient, PagingRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let paging = PagingRequest {
page_number: 1,
page_size: 10,
};
let response = client
.list_records(195, Some(paging), None, None)
.await?;
for record in response.items.unwrap_or_default() {
println!(
"AppId: {}, RecordId: {}",
record.app_id,
record.record_id
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -100,6 +100,34 @@ for record in response.data.records:
print(f'Value: {field.GetResultValueString()}') print(f'Value: {field.GetResultValueString()}')
``` ```
```rust
use onspring::{OnspringClient, BatchGetRecordsRequest, DataFormat};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let request = BatchGetRecordsRequest {
app_id: 195,
record_ids: vec![1],
field_ids: Some(vec![6983, 6986, 6987, 6985, 6984]),
data_format: Some(DataFormat::Raw),
};
let response = client
.batch_get_records(request)
.await?;
for record in response.items.unwrap_or_default() {
println!(
"AppId: {}, RecordId: {}",
record.app_id,
record.record_id
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -126,6 +126,34 @@ for record in response.data.records:
print(f'Value: {field.GetResultValueString()}') print(f'Value: {field.GetResultValueString()}')
``` ```
```rust
use onspring::{OnspringClient, QueryRecordsRequest, DataFormat};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let query = QueryRecordsRequest {
app_id: 195,
filter: "6983 eq 'Test Task 5'".to_string(),
field_ids: Some(vec![6983, 6986, 6987, 6985, 6984]),
data_format: Some(DataFormat::Formatted),
};
let response = client
.query_records(query, None)
.await?;
for record in response.items.unwrap_or_default() {
println!(
"AppId: {}, RecordId: {}",
record.app_id,
record.record_id
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -123,6 +123,48 @@ for warning in response.data.warnings:
print(f'Warning: {warning}') print(f'Warning: {warning}')
``` ```
```rust
use onspring::{OnspringClient, SaveRecordRequest};
use std::collections::HashMap;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let mut fields = HashMap::new();
fields.insert(
"6983".to_string(),
serde_json::json!("A New Test Task"),
);
fields.insert(
"6984".to_string(),
serde_json::json!("This is a test task."),
);
fields.insert(
"6985".to_string(),
serde_json::json!("12/25/2021"),
);
fields.insert(
"6986".to_string(),
serde_json::json!("4118d53a-9121-4345-8682-07f23d606daa"),
);
fields.insert(
"6987".to_string(),
serde_json::json!([4]),
);
let request = SaveRecordRequest {
app_id: 195,
record_id: None,
fields,
};
let response = client.save_record(request).await?;
println!("New Record Id is: {}", response.id);
```
{% /code %} {% /code %}
{% code heading="Response" defaultLanguage="json" %} {% code heading="Response" defaultLanguage="json" %}
@@ -64,6 +64,31 @@ for row in response.data.rows:
print(f'Record Id {row.recordId}: {", ".join([str(cell) for cell in row.cells])}') print(f'Record Id {row.recordId}: {", ".join([str(cell) for cell in row.cells])}')
``` ```
```rust
use onspring::OnspringClient;
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let data = client
.get_report(613, None, None)
.await?;
println!("Columns: {:?}", data.columns);
if let Some(rows) = data.rows {
for row in rows {
println!(
"Record Id {:?}: {:?}",
row.record_id,
row.cells
);
}
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
@@ -64,6 +64,33 @@ for report in response.data.reports:
print(f' Description: {report.description}') print(f' Description: {report.description}')
``` ```
```rust
use onspring::{OnspringClient, PagingRequest};
let client = OnspringClient::builder(
"000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000"
)
.build();
let paging = PagingRequest {
page_number: 1,
page_size: 10,
};
let response = client
.list_reports(195, Some(paging))
.await?;
for report in response.items.unwrap_or_default() {
println!(
"{}, {}, {}",
report.id,
report.app_id,
report.name.unwrap_or_default()
);
}
```
{% /code %} {% /code %}
{% code heading="RESPONSE" defaultLanguage="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
+21 -7
View File
@@ -1,7 +1,11 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@@ -9,10 +13,10 @@
"noEmit": true, "noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve", "jsx": "react-jsx",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {
@@ -20,9 +24,19 @@
} }
], ],
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": [
"./src/*"
]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": [
"exclude": ["node_modules"] "next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
} }