datocms-plugin-alt-text-ai 0.5.2 → 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/public/index.html DELETED
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- </head>
7
- <body>
8
- <noscript>You need to enable JavaScript to run this app.</noscript>
9
- <div id="root"></div>
10
- </body>
11
- </html>
package/public/robots.txt DELETED
@@ -1,3 +0,0 @@
1
- # https://www.robotstxt.org/robotstxt.html
2
- User-agent: *
3
- Disallow:
@@ -1,129 +0,0 @@
1
- import { Client, buildClient } from "@datocms/cma-client-browser";
2
- import {
3
- type FileFieldValue,
4
- RenderFieldExtensionCtx,
5
- } from "datocms-plugin-sdk";
6
- import { Button, Canvas, Spinner } from "datocms-react-ui";
7
- import { isArray } from "lodash";
8
- import get from "lodash/get";
9
- import { useState } from "react";
10
-
11
- type PropTypes = {
12
- ctx: RenderFieldExtensionCtx;
13
- };
14
-
15
- async function fetchAlt(apiKey: string, client: Client, asset: FileFieldValue) {
16
- const { url } = await client.uploads.find(asset.upload_id);
17
-
18
- // Instead of sending over files that are possibly too big or the wrong format, etc.,
19
- // we'll use Imgix to pre-transform them into a valid format and smaller size
20
- let transformedUrl = new URL(url);
21
- transformedUrl.searchParams.set("fm", "jpeg");
22
- transformedUrl.searchParams.set("w", "1024");
23
-
24
- const result = await (
25
- await fetch("https://alttext.ai/api/v1/images", {
26
- method: "POST",
27
- headers: {
28
- "Content-Type": "application/json",
29
- "X-API-Key": apiKey ?? "",
30
- },
31
- body: JSON.stringify({
32
- image: {
33
- url: transformedUrl.toString(),
34
- },
35
- }),
36
- })
37
- ).json();
38
-
39
- return result;
40
- }
41
-
42
- async function generateAlts(
43
- currentFieldValue: unknown,
44
- ctx: RenderFieldExtensionCtx,
45
- setIsLoading: React.Dispatch<React.SetStateAction<boolean>>,
46
- ) {
47
- if (!ctx.currentUserAccessToken) {
48
- await ctx.alert(
49
- "This plugin needs the currentUserAccessToken to function. Please give it that permission and try again.",
50
- );
51
- return;
52
- }
53
-
54
- setIsLoading(true);
55
- try {
56
- const client = buildClient({ apiToken: ctx.currentUserAccessToken || "" });
57
- const isGallery = isArray(currentFieldValue);
58
- if (isGallery) {
59
- const existingAssets = currentFieldValue as FileFieldValue[];
60
- const newAssets = [];
61
- for (const asset of existingAssets) {
62
- console.log("asset", asset);
63
- const result = await fetchAlt(
64
- ctx.plugin.attributes.parameters.apiKey as string,
65
- client,
66
- asset,
67
- );
68
-
69
- if (result.error_code) {
70
- ctx.alert(
71
- `Alt text error for <a href="/media/assets/${asset.upload_id}" target="_blank">image ${asset.upload_id}</a>: <code>${result.error_code}: ${result.errors?.base?.[0] ?? ""}</code>`,
72
- );
73
- }
74
-
75
- asset.alt = result.alt_text;
76
- newAssets.push(asset);
77
- }
78
- ctx.setFieldValue(ctx.fieldPath, newAssets);
79
- } else {
80
- const assetValue = currentFieldValue as FileFieldValue;
81
-
82
- const result = await fetchAlt(
83
- ctx.plugin.attributes.parameters.apiKey as string,
84
- client,
85
- assetValue,
86
- );
87
-
88
- if (result.error_code) {
89
- await ctx.alert(
90
- `Error fetching alt text: <code>${result.error_code}: ${result.errors?.base?.[0] ?? ""}</code>`,
91
- );
92
- return;
93
- }
94
-
95
- assetValue.alt = result.alt_text;
96
- ctx.setFieldValue(ctx.fieldPath, assetValue);
97
- }
98
- } catch (error) {
99
- console.log(error);
100
- } finally {
101
- setIsLoading(false);
102
- }
103
- }
104
-
105
- const AltTextAIButton = ({ ctx }: PropTypes) => {
106
- const [isLoading, setIsLoading] = useState(false);
107
- const currentFieldValue = get(ctx.formValues, ctx.fieldPath);
108
- const isGallery = isArray(currentFieldValue);
109
- const isGalleryWithItems =
110
- isArray(currentFieldValue) && currentFieldValue.length;
111
-
112
- return (
113
- <Canvas ctx={ctx}>
114
- {(isGalleryWithItems || (!isGallery && !!currentFieldValue)) && (
115
- <Button
116
- fullWidth
117
- disabled={isLoading}
118
- onClick={() => {
119
- generateAlts(currentFieldValue, ctx, setIsLoading);
120
- }}
121
- >
122
- Generate Alt Text {isLoading && <Spinner size={24} />}
123
- </Button>
124
- )}
125
- </Canvas>
126
- );
127
- };
128
-
129
- export default AltTextAIButton;
@@ -1,66 +0,0 @@
1
- import { RenderConfigScreenCtx } from 'datocms-plugin-sdk';
2
- import {
3
- Button,
4
- Canvas,
5
- ContextInspector,
6
- Spinner,
7
- TextField,
8
- } from 'datocms-react-ui';
9
- import s from './styles.module.css';
10
- import { useState } from 'react';
11
-
12
- type Props = {
13
- ctx: RenderConfigScreenCtx;
14
- };
15
-
16
- async function saveApiKey(
17
- ctx: RenderConfigScreenCtx,
18
- apiKey: string,
19
- setIsLoading: React.Dispatch<React.SetStateAction<boolean>>
20
- ) {
21
- setIsLoading(true);
22
- await ctx.updatePluginParameters({ apiKey });
23
- setIsLoading(false);
24
- ctx.customToast({
25
- type: 'notice',
26
- message: 'API Key Saved!',
27
- dismissOnPageChange: true,
28
- dismissAfterTimeout: 5000,
29
- });
30
- }
31
-
32
- export default function ConfigScreen({ ctx }: Props) {
33
- const [apiKey, setApiKey] = useState(
34
- (ctx.plugin.attributes.parameters.apiKey as string) ?? ''
35
- );
36
- const [isLoading, setIsLoading] = useState(false);
37
-
38
- return (
39
- <Canvas ctx={ctx}>
40
- <div className={s.form}>
41
- <TextField
42
- required
43
- name="altTextAPIKey"
44
- id="altTextAPIKey"
45
- label="Alt Text API Key"
46
- value={apiKey}
47
- onChange={(newValue) => setApiKey(newValue)}
48
- />
49
- <p>
50
- You can get your API key by going to{' '}
51
- <a href="https://alttext.ai/account/api_keys" target="_blank">
52
- https://alttext.ai/account/api_keys
53
- </a>
54
- </p>
55
- </div>
56
-
57
- <Button
58
- disabled={isLoading}
59
- fullWidth
60
- onClick={() => saveApiKey(ctx, apiKey, setIsLoading)}
61
- >
62
- Save {isLoading && <Spinner size={24} />}
63
- </Button>
64
- </Canvas>
65
- );
66
- }
@@ -1,7 +0,0 @@
1
- .inspector {
2
- margin-top: var(--spacing-l);
3
- }
4
-
5
- .form {
6
- margin-bottom: 1rem;
7
- }
package/src/index.tsx DELETED
@@ -1,27 +0,0 @@
1
- import { render } from './utils/render';
2
- import ConfigScreen from './entrypoints/ConfigScreen';
3
- import 'datocms-react-ui/styles.css';
4
- import { connect, Field, RenderFieldExtensionCtx } from 'datocms-plugin-sdk';
5
- import AltTextAIButton from './entrypoints/AltTextAIButton';
6
-
7
- connect({
8
- renderConfigScreen(ctx) {
9
- return render(<ConfigScreen ctx={ctx} />);
10
- },
11
- overrideFieldExtensions(field: Field) {
12
- if (
13
- field.attributes.field_type === 'gallery' ||
14
- field.attributes.field_type === 'file'
15
- ) {
16
- return {
17
- addons: [{ id: 'altTextAI' }],
18
- };
19
- }
20
- },
21
- renderFieldExtension(fieldExtensionId: string, ctx: RenderFieldExtensionCtx) {
22
- switch (fieldExtensionId) {
23
- case 'altTextAI':
24
- return render(<AltTextAIButton ctx={ctx} />);
25
- }
26
- },
27
- });
@@ -1 +0,0 @@
1
- /// <reference types="react-scripts" />
@@ -1,9 +0,0 @@
1
- import React, { StrictMode } from 'react';
2
- import { createRoot } from 'react-dom/client';
3
-
4
- const container = document.getElementById('root');
5
- const root = createRoot(container!);
6
-
7
- export function render(component: React.ReactNode): void {
8
- root.render(<StrictMode>{component}</StrictMode>);
9
- }
package/tsconfig.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es5",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "esnext"
8
- ],
9
- "allowJs": true,
10
- "skipLibCheck": true,
11
- "esModuleInterop": true,
12
- "allowSyntheticDefaultImports": true,
13
- "strict": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "noFallthroughCasesInSwitch": true,
16
- "module": "esnext",
17
- "moduleResolution": "node",
18
- "resolveJsonModule": true,
19
- "isolatedModules": true,
20
- "noEmit": true,
21
- "jsx": "react-jsx"
22
- },
23
- "include": [
24
- "src"
25
- ]
26
- }
File without changes