├── .nvmrc ├── .gitignore ├── src ├── index.ts ├── get-root-path.ts ├── shims.d.ts └── interface.vue ├── package.json ├── tsconfig.json └── Readme.md /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.16.0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | .idea 4 | node_modules 5 | dist 6 | 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { defineInterface } from '@directus/extensions-sdk'; 2 | import InterfaceComponent from './interface.vue'; 3 | 4 | export default defineInterface({ 5 | id: 'uuid-file-image', 6 | name: 'UUID File Image', 7 | icon: 'box', 8 | description: 'Select image from Library in a UUID string field', 9 | component: InterfaceComponent, 10 | options: null, 11 | types: ['uuid'], 12 | }); 13 | -------------------------------------------------------------------------------- /src/get-root-path.ts: -------------------------------------------------------------------------------- 1 | export function getRootPath(): string { 2 | const path = window.location.pathname; 3 | const parts = path.split('/'); 4 | const adminIndex = parts.indexOf('admin'); 5 | const rootPath = parts.slice(0, adminIndex).join('/') + '/'; 6 | return rootPath; 7 | } 8 | 9 | export function getPublicURL(): string { 10 | const path = window.location.href; 11 | const parts = path.split('/'); 12 | const adminIndex = parts.indexOf('admin'); 13 | const rootPath = parts.slice(0, adminIndex).join('/') + '/'; 14 | return rootPath; 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "directus-interface-uuid-file-image", 3 | "description": "", 4 | "icon": "extension", 5 | "version": "1.0.0", 6 | "keywords": [ 7 | "directus", 8 | "directus-extension", 9 | "directus-custom-interface" 10 | ], 11 | "type": "module", 12 | "directus:extension": { 13 | "type": "interface", 14 | "path": "dist/index.js", 15 | "source": "src/index.ts", 16 | "host": "^10.1.7" 17 | }, 18 | "scripts": { 19 | "build": "directus-extension build", 20 | "dev": "directus-extension build -w --no-minify", 21 | "link": "directus-extension link" 22 | }, 23 | "devDependencies": { 24 | "@directus/extensions-sdk": "^10.1.0", 25 | "typescript": "^5.1.6", 26 | "vue": "^3.3.4" 27 | }, 28 | "dependencies": { 29 | "nanoid": "^4.0.2", 30 | "sass": "^1.64.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "lib": ["ES2019", "DOM"], 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "noFallthroughCasesInSwitch": true, 8 | "esModuleInterop": true, 9 | "noImplicitAny": true, 10 | "noImplicitThis": true, 11 | "noImplicitReturns": true, 12 | "noUnusedLocals": true, 13 | "noUncheckedIndexedAccess": true, 14 | "noUnusedParameters": true, 15 | "alwaysStrict": true, 16 | "strictNullChecks": true, 17 | "strictFunctionTypes": true, 18 | "strictBindCallApply": true, 19 | "strictPropertyInitialization": true, 20 | "resolveJsonModule": false, 21 | "skipLibCheck": true, 22 | "forceConsistentCasingInFileNames": true, 23 | "allowSyntheticDefaultImports": true, 24 | "isolatedModules": true, 25 | "rootDir": "./src" 26 | }, 27 | "include": ["./src/**/*.ts"] 28 | } 29 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Switch to node v18.16.0 (using .nvmrc) : 4 | ```bash 5 | nvm use 6 | ``` 7 | 8 | Install and build : 9 | ```bash 10 | npm ci 11 | npm run build 12 | ``` 13 | 14 | Then, move the built `dist/index.js` file into a new directory of your `extensions/interfaces`, for example `extensions/interfaces/uuid-file-image/index.js`. 15 | 16 | That's it! 17 | 18 | If you use docker, don't forget to mount the `interfaces` volume pointing to the directory containing `uuid-file-image/index.js`: 19 | ```yaml 20 | volumes: 21 | - ./path/to/local/interfaces:/directus/extensions/interfaces/ 22 | ``` 23 | 24 | # Example of usage in a JSON repeater field 25 | 26 | ![Capture d’écran 2021-11-23 à 09 57 53](https://user-images.githubusercontent.com/17531455/142995390-b8484d50-d461-4e2a-a8a2-4ba7d7067c5d.png) 27 | 28 | 29 | # To do (next version) 30 | 31 | When the file's selected, I currently set in uuid field the `filename_disk` key of the file. 32 | 33 | I wanted this to be set by the user into interface options (`props.file_key_to_get`: `String`), but I didn't added it yet in `src/index.ts`. 34 | -------------------------------------------------------------------------------- /src/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue'; 3 | const component: DefineComponent<{}, {}, any>; 4 | export default component; 5 | } 6 | 7 | declare module '*.md' { 8 | import { DefineComponent } from 'vue'; 9 | // eslint-disable-next-line @typescript-eslint/ban-types 10 | const component: DefineComponent<{}, {}, any>; 11 | export default component; 12 | } 13 | 14 | declare module '*.yaml' { 15 | const value: Record; 16 | export default value; 17 | } 18 | 19 | declare module '*.json' { 20 | const value: Record; 21 | export default value; 22 | } 23 | 24 | declare module 'jsonlint-mod' { 25 | const x: any; 26 | export default x; 27 | } 28 | 29 | declare module 'frappe-charts/src/js/charts/AxisChart' { 30 | export class Chart { 31 | constructor(element: string, options: Record); 32 | } 33 | } 34 | 35 | declare module '@directus-extensions-interface' { 36 | import { InterfaceConfig } from '@directus/shared/types'; 37 | const interfaces: InterfaceConfig[]; 38 | export default interfaces; 39 | } 40 | 41 | declare module '@directus-extensions-display' { 42 | import { DisplayConfig } from './directus/app/shared/types'; 43 | const displays: DisplayConfig[]; 44 | export default displays; 45 | } 46 | 47 | declare module '@directus-extensions-layout' { 48 | import { LayoutConfig } from './directus/app/shared/types'; 49 | const layouts: LayoutConfig[]; 50 | export default layouts; 51 | } 52 | 53 | declare module '@directus-extensions-panel' { 54 | import { PanelConfig } from './directus/app/shared/types'; 55 | const panel: PanelConfig[]; 56 | export default panel; 57 | } 58 | 59 | declare module '@directus-extensions-module' { 60 | import { ModuleConfig } from './directus/app/shared/types'; 61 | const modules: ModuleConfig[]; 62 | export default modules; 63 | } 64 | -------------------------------------------------------------------------------- /src/interface.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 257 | 258 | --------------------------------------------------------------------------------