diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 140cda0054..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,25 +0,0 @@ -**For security issues, please email support@getdirectus.com directly.** - -To help us resolve your issue more quickly, please use the following template: - -For feature requests/voting please use the [Directus Request Tool](https://request.getdirectus.com/), or come chat with us through [getdirectus.com](http://getdirectus.com). Accepted feature requests will be added to GitHub Issues for assignment. - -## Version Info - - Directus API version (Or commit hash): - - PHP version: - - MySQL version: - - Web server: (Ex. Apache, nginx or IIS?) - - OS name and version: - -## Expected Behavior - - -## Actual Behavior - - -## Steps to Reproduce - 1. - 2. - 3. - -## Schema Dump, Logs, or Screenshots diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 361c89d3f8..67e8b28c13 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -5,6 +5,8 @@ about: Create a report to help us improve --- -
- - link {{ url }} - - -
- - - - - - - - - - - - diff --git a/extensions/core/interfaces/file-preview/meta.json b/extensions/core/interfaces/file-preview/meta.json deleted file mode 100644 index 1eecd42a7d..0000000000 --- a/extensions/core/interfaces/file-preview/meta.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "$t:file_preview", - "version": "1.0.0", - "types": ["string"], - "hideLabel": true, - "icon": "image", - "options": { - "edit": { - "name": "$t:edit", - "interface": "checkboxes", - "default": ["image_editor"], - "options": { - "choices": { - "image_editor": "Image Editor" - } - } - } - }, - "translation": { - "en-US": { - "file_preview": "File Preview", - "edit": "Editing Options" - } - } -} diff --git a/extensions/core/interfaces/file-preview/package.json b/extensions/core/interfaces/file-preview/package.json deleted file mode 100644 index b6a3d9312c..0000000000 --- a/extensions/core/interfaces/file-preview/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@directus/file-preview", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "cropperjs": "^1.4.2" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/interfaces/file-size/display.vue b/extensions/core/interfaces/file-size/display.vue deleted file mode 100644 index 4f5f872080..0000000000 --- a/extensions/core/interfaces/file-size/display.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/extensions/core/interfaces/file-size/format-size.js b/extensions/core/interfaces/file-size/format-size.js deleted file mode 100644 index 6f2356ce90..0000000000 --- a/extensions/core/interfaces/file-size/format-size.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Convert a value in bytes to a human readable format - * @param {number} value The value in bytes to format - * @return {string} The human readable filesize - * @example - * - * const byteSize = 1500; - * const fileSize = formatSize(byteSize); - * // => '1.5 KB' - * @see https://stackoverflow.com/a/14919494/4859211 - */ -export default function formatSize(bytes = 0, decimal = true) { - const threshold = decimal ? 1000 : 1024; - - if (Boolean(bytes) === false) { - return "--"; - } - - if (Math.abs(bytes) < threshold) { - return `${bytes} B`; - } - - const units = decimal - ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] - : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]; - - let unitIndex = -1; - let remainingBytes = bytes; - - do { - remainingBytes /= threshold; - unitIndex += 1; - } while ( - Math.abs(remainingBytes) >= threshold && - unitIndex < units.length - 1 - ); - - return `${remainingBytes.toFixed(1)} ${units[unitIndex]}`; -} diff --git a/extensions/core/interfaces/file-size/input.vue b/extensions/core/interfaces/file-size/input.vue deleted file mode 100644 index a7154e9ad5..0000000000 --- a/extensions/core/interfaces/file-size/input.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/file-size/meta.json b/extensions/core/interfaces/file-size/meta.json deleted file mode 100644 index 3bb538f0fd..0000000000 --- a/extensions/core/interfaces/file-size/meta.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "$t:file_size", - "version": "1.0.1", - "types": ["integer"], - "icon": "storage", - "recommended": { - "length": 10 - }, - "options": { - "placeholder": { - "name": "$t:placeholder", - "interface": "text-input", - "comment": "$t:placeholder_comment", - "length": 200 - }, - "format": { - "name": "$t:format", - "comment": "$t:format_comment", - "interface": "toggle", - "default": true - }, - "formatInput": { - "name": "$t:format_input", - "comment": "$t:format_input_comment", - "interface": "toggle", - "default": true - }, - "decimal": { - "name": "$t:decimal", - "comment": "$t:decimal_comment", - "interface": "toggle", - "default": true - } - }, - "translation": { - "en-US": { - "file_size": "File Size", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "format": "Format value", - "format_comment": "Show the value in a human readable way (e.g. 10MB)", - "format_input": "Format input", - "format_input_comment": "Enter the value using a dropdown for units", - "decimal": "Decimal", - "decimal_comment": "Show the value in decimal counting (10MB vs 10MiB)" - } - } -} diff --git a/extensions/core/interfaces/file/display.vue b/extensions/core/interfaces/file/display.vue deleted file mode 100644 index 4f0137bb6d..0000000000 --- a/extensions/core/interfaces/file/display.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/file/get-icon.js b/extensions/core/interfaces/file/get-icon.js deleted file mode 100644 index 0824581fad..0000000000 --- a/extensions/core/interfaces/file/get-icon.js +++ /dev/null @@ -1,27 +0,0 @@ -export default function getIcon(type) { - if (type === "application/pdf") { - return "picture_as_pdf"; - } - - if (type.startsWith("application")) { - return "insert_drive_file"; - } - - if (type.startsWith("image")) { - return "crop_original"; - } - - if (type.startsWith("video")) { - return "videocam"; - } - - if (type.startsWith("code")) { - return "code"; - } - - if (type.startsWith("audio")) { - return "audiotrack"; - } - - return "save"; -} diff --git a/extensions/core/interfaces/file/input.vue b/extensions/core/interfaces/file/input.vue deleted file mode 100644 index 1b3b22fa40..0000000000 --- a/extensions/core/interfaces/file/input.vue +++ /dev/null @@ -1,253 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/file/meta.json b/extensions/core/interfaces/file/meta.json deleted file mode 100644 index 6f00ebab85..0000000000 --- a/extensions/core/interfaces/file/meta.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "$t:file", - "version": "1.1.0", - "types": ["file"], - "icon": "insert_drive_file", - "recommended": { - "length": 10 - }, - "options": { - "viewType": { - "name": "$t:view_type", - "comment": "$t:view_type_comment", - "default": "cards", - "interface": "text-input" - }, - "viewOptions": { - "name": "$t:view_options", - "comment": "$t:view_options_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": { - "title": "title", - "subtitle": "type", - "content": "description", - "src": "data" - } - }, - "viewQuery": { - "name": "$t:view_query", - "comment": "$t:view_query_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": {} - }, - "filters": { - "name": "$t:filters", - "comment": "$t:filters_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": [] - }, - "accept": { - "name": "$t:accept", - "comment": "$t:accept_comment", - "interface": "text-input" - } - }, - "translation": { - "en-US": { - "file": "File", - "view_type": "View Type", - "view_type_comment": "Select in what way you want to view the files", - "view_options": "View Options", - "view_options_comment": "Set the view options to use for the files", - "view_query": "View Query", - "view_query_comment": "Set the view query to use for the files", - "filters": "Filters", - "filters_comment": "What filters to use", - "accept": "Accept File Types", - "accept_comment": "Set a list of MIME types that can be picked" - } - } -} diff --git a/extensions/core/interfaces/files/display.vue b/extensions/core/interfaces/files/display.vue deleted file mode 100644 index 9c4d814fcd..0000000000 --- a/extensions/core/interfaces/files/display.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/extensions/core/interfaces/files/get-icon.js b/extensions/core/interfaces/files/get-icon.js deleted file mode 100644 index 0824581fad..0000000000 --- a/extensions/core/interfaces/files/get-icon.js +++ /dev/null @@ -1,27 +0,0 @@ -export default function getIcon(type) { - if (type === "application/pdf") { - return "picture_as_pdf"; - } - - if (type.startsWith("application")) { - return "insert_drive_file"; - } - - if (type.startsWith("image")) { - return "crop_original"; - } - - if (type.startsWith("video")) { - return "videocam"; - } - - if (type.startsWith("code")) { - return "code"; - } - - if (type.startsWith("audio")) { - return "audiotrack"; - } - - return "save"; -} diff --git a/extensions/core/interfaces/files/input.vue b/extensions/core/interfaces/files/input.vue deleted file mode 100644 index 5169a9688c..0000000000 --- a/extensions/core/interfaces/files/input.vue +++ /dev/null @@ -1,450 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/files/meta.json b/extensions/core/interfaces/files/meta.json deleted file mode 100644 index 311845373d..0000000000 --- a/extensions/core/interfaces/files/meta.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "$t:files", - "version": "1.1.0", - "types": ["o2m"], - "relation": { - "type": "m2m", - "relatedCollection": "directus_files" - }, - "icon": "insert_drive_file", - "recommended": { - "length": 10 - }, - "options": { - "viewType": { - "name": "$t:view_type", - "comment": "$t:view_type_comment", - "default": "cards", - "interface": "text-input" - }, - "viewOptions": { - "name": "$t:view_options", - "comment": "$t:view_options_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": { - "title": "title", - "subtitle": "type", - "content": "description", - "src": "data" - } - }, - "viewQuery": { - "name": "$t:view_query", - "comment": "$t:view_query_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": {} - }, - "filters": { - "name": "$t:filters", - "comment": "$t:filters_comment", - "interface": "code", - "options": { - "language": "application/json" - }, - "default": [] - }, - "accept": { - "name": "$t:accept", - "comment": "$t:accept_comment", - "interface": "text-input" - } - }, - "translation": { - "en-US": { - "files": "Files", - "view_type": "View Type", - "view_type_comment": "Select in what way you want to view the files", - "view_options": "View Options", - "view_options_comment": "Set the view options to use for the files", - "view_query": "View Query", - "view_query_comment": "Set the view query to use for the files", - "filters": "Filters", - "filters_comment": "What filters to use", - "accept": "Accept File Types", - "accept_comment": "Set a list of MIME types that can be picked", - "edit_item": "Edit" - } - } -} diff --git a/extensions/core/interfaces/group/display.vue b/extensions/core/interfaces/group/display.vue deleted file mode 100644 index 04d85e1bdb..0000000000 --- a/extensions/core/interfaces/group/display.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/extensions/core/interfaces/group/input.vue b/extensions/core/interfaces/group/input.vue deleted file mode 100644 index f56cc1390d..0000000000 --- a/extensions/core/interfaces/group/input.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/extensions/core/interfaces/group/meta.json b/extensions/core/interfaces/group/meta.json deleted file mode 100644 index 20dbe68ddf..0000000000 --- a/extensions/core/interfaces/group/meta.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "$t:group", - "version": "1.0.0", - "types": ["group"], - "icon": "group_work", - "options": { - "open": { - "name": "$t:open", - "comment": "$t:open_comment", - "interface": "toggle", - "default": true, - "options": { - "labelOn": "Starts Open", - "labelOff": "Starts Closed" - } - }, - "title": { - "name": "$t:title", - "comment": "$t:title_comment", - "interface": "text-input" - } - }, - "translation": { - "en-US": { - "group": "Group", - "open": "Default state", - "open_comment": "Group is opened by default", - "title": "Title", - "title_comment": "Add a title to display" - } - } -} diff --git a/extensions/core/interfaces/hashed/display.vue b/extensions/core/interfaces/hashed/display.vue deleted file mode 100644 index 1cae498e1d..0000000000 --- a/extensions/core/interfaces/hashed/display.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/hashed/hooks.php b/extensions/core/interfaces/hashed/hooks.php deleted file mode 100644 index 46b561a948..0000000000 --- a/extensions/core/interfaces/hashed/hooks.php +++ /dev/null @@ -1,33 +0,0 @@ -getData(); - $container = Application::getInstance()->getContainer(); - $schemaManager = $container->get('schema_manager'); - $hashManager = $container->get('hash_manager'); - - $collection = $schemaManager->getCollection($payload->attribute('collection_name')); - $interfaceName = basename(__DIR__); - - foreach ($data as $fieldName => $value) { - $field = $collection->getField($fieldName); - if ($field && $field->getInterface() === $interfaceName) { - $options = $field->getOptions() ?: ['hasher' => 'core']; - - $hashedString = $hashManager->hash($value, $options); - $payload->set($fieldName, $hashedString); - } - } - - return $payload; -}; - -return [ - 'filters' => [ - 'item.create:before' => $hashValue, - 'item.update:before' => $hashValue, - ] -]; diff --git a/extensions/core/interfaces/hashed/input.vue b/extensions/core/interfaces/hashed/input.vue deleted file mode 100644 index 798776abae..0000000000 --- a/extensions/core/interfaces/hashed/input.vue +++ /dev/null @@ -1,60 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/hashed/meta.json b/extensions/core/interfaces/hashed/meta.json deleted file mode 100644 index 7cf02bf3ce..0000000000 --- a/extensions/core/interfaces/hashed/meta.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "$t:hashed", - "version": "1.0.1", - "types": ["string"], - "icon": "security", - "recommended": { - "length": 100 - }, - "options": { - "hide": { - "name": "$t:hide", - "comment": "$t:hide_comment", - "interface": "toggle", - "default": false - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 100, - "default": "Enter a value..." - }, - "showHash": { - "name": "$t:show_hash", - "comment": "$t:show_hash_comment", - "interface": "toggle", - "default": false - }, - "hashingType": { - "name": "$t:hashing_type", - "comment": "$t:hashing_type_comment", - "interface": "dropdown", - "default": "core", - "options": { - "choices": { - "core": "Default", - "bcrypt": "bcrypt", - "md5": "md5", - "sha1": "SHA-1", - "sha224": "SHA-224", - "sha256": "SHA-256", - "sha384": "SHA-384", - "sha512": "SHA-512" - } - } - } - }, - "translation": { - "en-US": { - "hashed": "Hashed", - "hide": "Hide Value", - "hide_comment": "Display dots instead of the characters you enter", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "show_hash": "Show the hashed output", - "show_hash_comment": "Display the saved hash", - "hashing_type": "Hashing Type", - "hashing_type_comment": "What method of hashing to use", - "width": "Size", - "width_comment": "Set what width to use for the input", - "auto": "Automatic", - "small": "Small", - "medium": "Medium", - "large": "Large", - "secured": "Value Secured" - } - } -} diff --git a/extensions/core/interfaces/icon/display.vue b/extensions/core/interfaces/icon/display.vue deleted file mode 100644 index aa21110e03..0000000000 --- a/extensions/core/interfaces/icon/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/icon/icons.json b/extensions/core/interfaces/icon/icons.json deleted file mode 100644 index 06bd165a30..0000000000 --- a/extensions/core/interfaces/icon/icons.json +++ /dev/null @@ -1,1034 +0,0 @@ -{ - "action": [ - "3d_rotation", - "accessibility", - "accessibility_new", - "accessible", - "accessible_forward", - "account_balance", - "account_balance_wallet", - "account_box", - "account_circle", - "add_shopping_cart", - "alarm", - "alarm_add", - "alarm_off", - "alarm_on", - "all_out", - "android", - "announcement", - "arrow_right_alt", - "aspect_ratio", - "assessment", - "assignment", - "assignment_ind", - "assignment_late", - "assignment_return", - "assignment_returned", - "assignment_turned_in", - "autorenew", - "backup", - "book", - "bookmark", - "bookmark_border", - "bug_report", - "build", - "cached", - "calendar_today", - "calendar_view_day", - "camera_enhance", - "card_giftcard", - "card_membership", - "card_travel", - "change_history", - "check_circle", - "check_circle_outline", - "chrome_reader_mode", - "class", - "code", - "commute", - "compare_arrows", - "contact_support", - "copyright", - "credit_card", - "dashboard", - "date_range", - "delete", - "delete_forever", - "delete_outline", - "description", - "dns", - "done", - "done_all", - "done_outline", - "donut_large", - "donut_small", - "drag_indicator", - "eject", - "euro_symbol", - "event", - "event_seat", - "exit_to_app", - "explore", - "extension", - "face", - "favorite", - "favorite_border", - "feedback", - "find_in_page", - "find_replace", - "fingerprint", - "flight_land", - "flight_takeoff", - "flip_to_back", - "flip_to_front", - "g_translate", - "gavel", - "get_app", - "gif", - "grade", - "group_work", - "help", - "help_outline", - "highlight_off", - "history", - "home", - "horizontal_split", - "hourglass_empty", - "hourglass_full", - "http", - "https", - "important_devices", - "info", - "input", - "invert_colors", - "label", - "label_important", - "language", - "launch", - "line_style", - "line_weight", - "list", - "lock", - "lock_open", - "loyalty", - "markunread_mailbox", - "maximize", - "minimize", - "motorcycle", - "note_add", - "offline_bolt", - "offline_pin", - "opacity", - "open_in_browser", - "open_in_new", - "open_with", - "pageview", - "pan_tool", - "payment", - "perm_camera_mic", - "perm_contact_calendar", - "perm_data_setting", - "perm_device_information", - "perm_identity", - "perm_media", - "perm_phone_msg", - "perm_scan_wifi", - "pets", - "picture_in_picture", - "picture_in_picture_alt", - "play_for_work", - "polymer", - "power_settings_new", - "pregnant_woman", - "print", - "query_builder", - "question_answer", - "receipt", - "record_voice_over", - "redeem", - "remove_shopping_cart", - "reorder", - "report_problem", - "restore", - "restore_from_trash", - "restore_page", - "room", - "rounded_corner", - "rowing", - "schedule", - "search", - "settings", - "settings_applications", - "settings_backup_restore", - "settings_bluetooth", - "settings_brightness", - "settings_cell", - "settings_ethernet", - "settings_input_antenna", - "settings_input_component", - "settings_input_composite", - "settings_input_hdmi", - "settings_input_svideo", - "settings_overscan", - "settings_phone", - "settings_power", - "settings_remote", - "settings_voice", - "shop", - "shop_two", - "shopping_basket", - "shopping_cart", - "speaker_notes", - "speaker_notes_off", - "spellcheck", - "stars", - "store", - "subject", - "supervised_user_circle", - "supervisor_account", - "swap_horiz", - "swap_horizontal_circle", - "swap_vert", - "swap_vertical_circle", - "tab", - "tab_unselected", - "text_rotate_up", - "text_rotate_vertical", - "text_rotation_down", - "text_rotation_none", - "theaters", - "thumb_down", - "thumb_up", - "thumbs_up_down", - "timeline", - "toc", - "today", - "toll", - "touch_app", - "track_changes", - "translate", - "trending_down", - "trending_flat", - "trending_up", - "turned_in", - "turned_in_not", - "update", - "verified_user", - "vertical_split", - "view_agenda", - "view_array", - "view_carousel", - "view_column", - "view_day", - "view_headline", - "view_list", - "view_module", - "view_quilt", - "view_stream", - "view_week", - "visibility", - "visibility_off", - "voice_over_off", - "watch_later", - "work", - "work_off", - "work_outline", - "youtube_searched_for", - "zoom_in", - "zoom_out" - ], - "alert": [ - "add_alert", - "error", - "error_outline", - "notification_important", - "warning" - ], - "av": [ - "4k", - "add_to_queue", - "airplay", - "album", - "art_track", - "av_timer", - "branding_watermark", - "call_to_action", - "closed_caption", - "control_camera", - "equalizer", - "explicit", - "fast_forward", - "fast_rewind", - "featured_play_list", - "featured_video", - "fiber_dvr", - "fiber_manual_record", - "fiber_new", - "fiber_pin", - "fiber_smart_record", - "forward_10", - "forward_30", - "forward_5", - "games", - "hd", - "hearing", - "high_quality", - "library_add", - "library_books", - "library_music", - "loop", - "mic", - "mic_none", - "mic_off", - "missed_video_call", - "movie", - "music_video", - "new_releases", - "not_interested", - "note", - "pause", - "pause_circle_filled", - "pause_circle_outline", - "play_arrow", - "play_circle_filled", - "play_circle_outline", - "playlist_add", - "playlist_add_check", - "playlist_play", - "queue", - "queue_music", - "queue_play_next", - "radio", - "recent_actors", - "remove_from_queue", - "repeat", - "repeat_one", - "replay", - "replay_10", - "replay_30", - "replay_5", - "shuffle", - "skip_next", - "skip_previous", - "slow_motion_video", - "snooze", - "sort_by_alpha", - "stop", - "subscriptions", - "subtitles", - "surround_sound", - "video_call", - "video_label", - "video_library", - "videocam", - "videocam_off", - "volume_down", - "volume_mute", - "volume_off", - "volume_up", - "web", - "web_asset" - ], - "communication": [ - "alternate_email", - "business", - "call", - "call_end", - "call_made", - "call_merge", - "call_missed", - "call_missed_outgoing", - "call_received", - "call_split", - "cancel_presentation", - "cell_wifi", - "chat", - "chat_bubble", - "chat_bubble_outline", - "clear_all", - "comment", - "contact_mail", - "contact_phone", - "contacts", - "dialer_sip", - "dialpad", - "domain_disabled", - "email", - "forum", - "import_contacts", - "import_export", - "invert_colors_off", - "list_alt", - "live_help", - "location_off", - "location_on", - "mail_outline", - "message", - "mobile_screen_share", - "no_sim", - "pause_presentation", - "phone", - "phonelink_erase", - "phonelink_lock", - "phonelink_ring", - "phonelink_setup", - "portable_wifi_off", - "present_to_all", - "ring_volume", - "rss_feed", - "screen_share", - "sentiment_satisfied_alt", - "speaker_phone", - "stay_current_landscape", - "stay_current_portrait", - "stay_primary_landscape", - "stay_primary_portrait", - "stop_screen_share", - "swap_calls", - "textsms", - "unsubscribe", - "voicemail", - "vpn_key" - ], - "content": [ - "add", - "add_box", - "add_circle", - "add_circle_outline", - "archive", - "backspace", - "ballot", - "block", - "clear", - "create", - "delete_sweep", - "drafts", - "file_copy", - "filter_list", - "flag", - "font_download", - "forward", - "gesture", - "how_to_reg", - "how_to_vote", - "inbox", - "link", - "link_off", - "low_priority", - "mail", - "markunread", - "move_to_inbox", - "next_week", - "outlined_flag", - "redo", - "remove", - "remove_circle", - "remove_circle_outline", - "reply", - "reply_all", - "report", - "report_off", - "save", - "save_alt", - "select_all", - "send", - "sort", - "text_format", - "unarchive", - "undo", - "waves", - "weekend", - "where_to_vote" - ], - "device": [ - "access_alarm", - "access_alarms", - "access_time", - "add_alarm", - "add_to_home_screen", - "airplanemode_active", - "airplanemode_inactive", - "battery_alert", - "battery_charging_full", - "battery_full", - "battery_std", - "battery_unknown", - "bluetooth", - "bluetooth_connected", - "bluetooth_disabled", - "bluetooth_searching", - "brightness_auto", - "brightness_high", - "brightness_low", - "brightness_medium", - "data_usage", - "developer_mode", - "devices", - "dvr", - "gps_fixed", - "gps_not_fixed", - "gps_off", - "graphic_eq", - "location_disabled", - "location_searching", - "mobile_friendly", - "mobile_off", - "network_cell", - "network_wifi", - "nfc", - "screen_lock_landscape", - "screen_lock_portrait", - "screen_lock_rotation", - "screen_rotation", - "sd_storage", - "settings_system_daydream", - "signal_cellular_alt", - "signal_cellular_no_sim", - "signal_cellular_null", - "signal_cellular_off", - "signal_wifi_off", - "storage", - "usb", - "wallpaper", - "widgets", - "wifi_lock", - "wifi_tethering" - ], - "editor": [ - "add_comment", - "attach_file", - "attach_money", - "bar_chart", - "border_all", - "border_bottom", - "border_clear", - "border_color", - "border_horizontal", - "border_inner", - "border_left", - "border_outer", - "border_right", - "border_style", - "border_top", - "border_vertical", - "bubble_chart", - "drag_handle", - "format_align_center", - "format_align_justify", - "format_align_left", - "format_align_right", - "format_bold", - "format_clear", - "format_color_fill", - "format_color_reset", - "format_color_text", - "format_indent_decrease", - "format_indent_increase", - "format_italic", - "format_line_spacing", - "format_list_bulleted", - "format_list_numbered", - "format_list_numbered_rtl", - "format_paint", - "format_quote", - "format_shapes", - "format_size", - "format_strikethrough", - "format_textdirection_l_to_r", - "format_textdirection_r_to_l", - "format_underlined", - "functions", - "highlight", - "insert_chart", - "insert_chart_outlined", - "insert_comment", - "insert_drive_file", - "insert_emoticon", - "insert_invitation", - "insert_link", - "insert_photo", - "linear_scale", - "merge_type", - "mode_comment", - "monetization_on", - "money_off", - "multiline_chart", - "notes", - "pie_chart", - "publish", - "scatter_plot", - "score", - "short_text", - "show_chart", - "space_bar", - "strikethrough_s", - "table_chart", - "text_fields", - "title", - "vertical_align_bottom", - "vertical_align_center", - "vertical_align_top", - "wrap_text" - ], - "file": [ - "attachment", - "cloud", - "cloud_circle", - "cloud_done", - "cloud_download", - "cloud_off", - "cloud_queue", - "cloud_upload", - "create_new_folder", - "folder", - "folder_open", - "folder_shared" - ], - "hardware": [ - "cast", - "cast_connected", - "computer", - "desktop_mac", - "desktop_windows", - "developer_board", - "device_hub", - "device_unknown", - "devices_other", - "dock", - "gamepad", - "headset", - "headset_mic", - "keyboard", - "keyboard_arrow_down", - "keyboard_arrow_left", - "keyboard_arrow_right", - "keyboard_arrow_up", - "keyboard_backspace", - "keyboard_capslock", - "keyboard_hide", - "keyboard_return", - "keyboard_tab", - "keyboard_voice", - "laptop", - "laptop_chromebook", - "laptop_mac", - "laptop_windows", - "memory", - "mouse", - "phone_android", - "phone_iphone", - "phonelink", - "phonelink_off", - "power_input", - "router", - "scanner", - "security", - "sim_card", - "smartphone", - "speaker", - "speaker_group", - "tablet", - "tablet_android", - "tablet_mac", - "toys", - "tv", - "videogame_asset", - "watch" - ], - "image": [ - "add_a_photo", - "add_photo_alternate", - "add_to_photos", - "adjust", - "assistant", - "assistant_photo", - "audiotrack", - "blur_circular", - "blur_linear", - "blur_off", - "blur_on", - "brightness_1", - "brightness_2", - "brightness_3", - "brightness_4", - "brightness_5", - "brightness_6", - "brightness_7", - "broken_image", - "brush", - "burst_mode", - "camera", - "camera_alt", - "camera_front", - "camera_rear", - "camera_roll", - "center_focus_strong", - "center_focus_weak", - "collections", - "collections_bookmark", - "color_lens", - "colorize", - "compare", - "control_point", - "control_point_duplicate", - "crop", - "crop_16_9", - "crop_3_2", - "crop_5_4", - "crop_7_5", - "crop_din", - "crop_free", - "crop_landscape", - "crop_original", - "crop_portrait", - "crop_rotate", - "crop_square", - "dehaze", - "details", - "edit", - "exposure", - "exposure_neg_1", - "exposure_neg_2", - "exposure_plus_1", - "exposure_plus_2", - "exposure_zero", - "filter", - "filter_1", - "filter_2", - "filter_3", - "filter_4", - "filter_5", - "filter_6", - "filter_7", - "filter_8", - "filter_9", - "filter_9_plus", - "filter_b_and_w", - "filter_center_focus", - "filter_drama", - "filter_frames", - "filter_hdr", - "filter_none", - "filter_tilt_shift", - "filter_vintage", - "flare", - "flash_auto", - "flash_off", - "flash_on", - "flip", - "gradient", - "grain", - "grid_off", - "grid_on", - "hdr_off", - "hdr_on", - "hdr_strong", - "hdr_weak", - "healing", - "image", - "image_aspect_ratio", - "image_search", - "iso", - "landscape", - "leak_add", - "leak_remove", - "lens", - "linked_camera", - "looks", - "looks_3", - "looks_4", - "looks_5", - "looks_6", - "looks_one", - "looks_two", - "loupe", - "monochrome_photos", - "movie_creation", - "movie_filter", - "music_note", - "music_off", - "nature", - "nature_people", - "navigate_before", - "navigate_next", - "palette", - "panorama", - "panorama_fish_eye", - "panorama_horizontal", - "panorama_vertical", - "panorama_wide_angle", - "photo", - "photo_album", - "photo_camera", - "photo_filter", - "photo_library", - "photo_size_select_actual", - "photo_size_select_large", - "photo_size_select_small", - "picture_as_pdf", - "portrait", - "remove_red_eye", - "rotate_90_degrees_ccw", - "rotate_left", - "rotate_right", - "shutter_speed", - "slideshow", - "straighten", - "style", - "switch_camera", - "switch_video", - "tag_faces", - "texture", - "timelapse", - "timer", - "timer_10", - "timer_3", - "timer_off", - "tonality", - "transform", - "tune", - "view_comfy", - "view_compact", - "vignette", - "wb_auto", - "wb_cloudy", - "wb_incandescent", - "wb_iridescent", - "wb_sunny" - ], - "maps": [ - "360", - "add_location", - "atm", - "beenhere", - "category", - "compass_calibration", - "departure_board", - "directions", - "directions_bike", - "directions_boat", - "directions_bus", - "directions_car", - "directions_railway", - "directions_run", - "directions_subway", - "directions_transit", - "directions_walk", - "edit_attributes", - "edit_location", - "ev_station", - "fastfood", - "flight", - "hotel", - "layers", - "layers_clear", - "local_activity", - "local_airport", - "local_atm", - "local_bar", - "local_cafe", - "local_car_wash", - "local_convenience_store", - "local_dining", - "local_drink", - "local_florist", - "local_gas_station", - "local_grocery_store", - "local_hospital", - "local_hotel", - "local_laundry_service", - "local_library", - "local_mall", - "local_movies", - "local_offer", - "local_parking", - "local_pharmacy", - "local_phone", - "local_pizza", - "local_play", - "local_post_office", - "local_printshop", - "local_see", - "local_shipping", - "local_taxi", - "map", - "money", - "my_location", - "navigation", - "near_me", - "not_listed_location", - "person_pin", - "person_pin_circle", - "pin_drop", - "place", - "rate_review", - "restaurant", - "restaurant_menu", - "satellite", - "store_mall_directory", - "streetview", - "subway", - "terrain", - "traffic", - "train", - "tram", - "transfer_within_a_station", - "transit_enterexit", - "trip_origin", - "zoom_out_map" - ], - "navigation": [ - "apps", - "arrow_back", - "arrow_back_ios", - "arrow_downward", - "arrow_drop_down", - "arrow_drop_down_circle", - "arrow_drop_up", - "arrow_forward", - "arrow_forward_ios", - "arrow_left", - "arrow_right", - "arrow_upward", - "cancel", - "check", - "chevron_left", - "chevron_right", - "close", - "expand_less", - "expand_more", - "first_page", - "fullscreen", - "fullscreen_exit", - "last_page", - "menu", - "more_horiz", - "more_vert", - "refresh", - "subdirectory_arrow_left", - "subdirectory_arrow_right", - "unfold_less", - "unfold_more" - ], - "notification": [ - "adb", - "airline_seat_flat", - "airline_seat_flat_angled", - "airline_seat_individual_suite", - "airline_seat_legroom_extra", - "airline_seat_legroom_normal", - "airline_seat_legroom_reduced", - "airline_seat_recline_extra", - "airline_seat_recline_normal", - "bluetooth_audio", - "confirmation_number", - "disc_full", - "drive_eta", - "enhanced_encryption", - "event_available", - "event_busy", - "event_note", - "folder_special", - "live_tv", - "mms", - "more", - "network_check", - "network_locked", - "no_encryption", - "ondemand_video", - "personal_video", - "phone_bluetooth_speaker", - "phone_callback", - "phone_forwarded", - "phone_in_talk", - "phone_locked", - "phone_missed", - "phone_paused", - "power", - "power_off", - "priority_high", - "sd_card", - "sms", - "sms_failed", - "sync", - "sync_disabled", - "sync_problem", - "system_update", - "tap_and_play", - "time_to_leave", - "tv_off", - "vibration", - "voice_chat", - "vpn_lock", - "wc", - "wifi", - "wifi_off" - ], - "places": [ - "ac_unit", - "airport_shuttle", - "all_inclusive", - "beach_access", - "business_center", - "casino", - "child_care", - "child_friendly", - "fitness_center", - "free_breakfast", - "golf_course", - "hot_tub", - "kitchen", - "meeting_room", - "no_meeting_room", - "pool", - "room_service", - "rv_hookup", - "smoke_free", - "smoking_rooms", - "spa" - ], - "social": [ - "cake", - "domain", - "group", - "group_add", - "location_city", - "mood", - "mood_bad", - "notifications", - "notifications_active", - "notifications_none", - "notifications_off", - "notifications_paused", - "pages", - "party_mode", - "people", - "people_outline", - "person", - "person_add", - "person_outline", - "plus_one", - "poll", - "public", - "school", - "sentiment_dissatisfied", - "sentiment_satisfied", - "sentiment_very_dissatisfied", - "sentiment_very_satisfied", - "share", - "thumb_down_alt", - "thumb_up_alt", - "whatshot" - ], - "toggle": [ - "check_box", - "check_box_outline_blank", - "indeterminate_check_box", - "radio_button_checked", - "radio_button_unchecked", - "star", - "star_border", - "star_half" - ] -} \ No newline at end of file diff --git a/extensions/core/interfaces/icon/input.vue b/extensions/core/interfaces/icon/input.vue deleted file mode 100644 index cfabfd3a1a..0000000000 --- a/extensions/core/interfaces/icon/input.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/icon/meta.json b/extensions/core/interfaces/icon/meta.json deleted file mode 100644 index b4a9b1e70e..0000000000 --- a/extensions/core/interfaces/icon/meta.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "$t:icon", - "version": "1.0.1", - "types": ["string"], - "icon": "insert_emoticon", - "recommended": { - "length": 20 - }, - "options": {}, - "translation": { - "en-US": { - "icon": "Icon", - "search_placeholder": "Search for an icon..." - } - } -} diff --git a/extensions/core/interfaces/language/display.vue b/extensions/core/interfaces/language/display.vue deleted file mode 100644 index b50f9d9482..0000000000 --- a/extensions/core/interfaces/language/display.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/extensions/core/interfaces/language/input.vue b/extensions/core/interfaces/language/input.vue deleted file mode 100644 index 8242a3d532..0000000000 --- a/extensions/core/interfaces/language/input.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/language/languages.json b/extensions/core/interfaces/language/languages.json deleted file mode 100644 index ed9c6e390a..0000000000 --- a/extensions/core/interfaces/language/languages.json +++ /dev/null @@ -1,230 +0,0 @@ -{ - "af": "Afrikaans", - "af-ZA": "Afrikaans (South Africa)", - "sq": "Albanian", - "sq-AL": "Albanian (Albania)", - "ar": "Arabic", - "ar-DZ": "Arabic (Algeria)", - "ar-BH": "Arabic (Bahrain)", - "ar-EG": "Arabic (Egypt)", - "ar-IQ": "Arabic (Iraq)", - "ar-JO": "Arabic (Jordan)", - "ar-KW": "Arabic (Kuwait)", - "ar-LB": "Arabic (Lebanon)", - "ar-LY": "Arabic (Libya)", - "ar-MA": "Arabic (Morocco)", - "ar-OM": "Arabic (Oman)", - "ar-QA": "Arabic (Qatar)", - "ar-SA": "Arabic (Saudi Arabia)", - "ar-SY": "Arabic (Syria)", - "ar-TN": "Arabic (Tunisia)", - "ar-AE": "Arabic (U.A.E.)", - "ar-YE": "Arabic (Yemen)", - "hy-AM": "Armenian (Armenia)", - "hy": "Armenian", - "az-AZ": "Azeri (Cyrillic) (Azerbaijan)", - "az": "Azeri (Latin)", - "eu": "Basque", - "eu-ES": "Basque (Spain)", - "be": "Belarusian", - "be-BY": "Belarusian (Belarus)", - "bs-BA": "Bosnian (Bosnia and Herzegovina)", - "bg": "Bulgarian", - "bg-BG": "Bulgarian (Bulgaria)", - "ca": "Catalan", - "ca-ES": "Catalan (Spain)", - "zh": "Chinese", - "zh-HK": "Chinese (Hong Kong)", - "zh-MO": "Chinese (Macau)", - "zh-CN": "Chinese (S)", - "zh-SG": "Chinese (Singapore)", - "zh-TW": "Chinese (T)", - "hr": "Croatian", - "hr-BA": "Croatian (Bosnia and Herzegovina)", - "hr-HR": "Croatian (Croatia)", - "cs": "Czech", - "cs-CZ": "Czech (Czech Republic)", - "da": "Danish", - "da-DK": "Danish (Denmark)", - "dv": "Divehi", - "dv-MV": "Divehi (Maldives)", - "nl": "Dutch", - "nl-BE": "Dutch (Belgium)", - "nl-NL": "Dutch (Netherlands)", - "en": "English", - "en-AU": "English (Australia)", - "en-BZ": "English (Belize)", - "en-CA": "English (Canada)", - "en-CB": "English (Caribbean)", - "en-IE": "English (Ireland)", - "en-JM": "English (Jamaica)", - "en-NZ": "English (New Zealand)", - "en-PH": "English (Republic of the Philippines)", - "en-ZA": "English (South Africa)", - "en-TT": "English (Trinidad and Tobago)", - "en-GB": "English (United Kingdom)", - "en-US": "English (United States)", - "en-ZW": "English (Zimbabwe)", - "eo": "Esperanto", - "et": "Estonian", - "et-EE": "Estonian (Estonia)", - "fo": "Faroese", - "fo-FO": "Faroese (Faroe Islands)", - "fa": "Farsi", - "fa-IR": "Farsi (Iran)", - "fi": "Finnish", - "fi-FI": "Finnish (Finland)", - "fr": "French", - "fr-BE": "French (Belgium)", - "fr-CA": "French (Canada)", - "fr-FR": "French (France)", - "fr-LU": "French (Luxembourg)", - "fr-MC": "French (Principality of Monaco)", - "fr-CH": "French (Switzerland)", - "mk": "FYRO Macedonian", - "mk-MK": "FYRO Macedonian (Former Yugoslav Republic of Macedonia)", - "gl": "Galician", - "gl-ES": "Galician (Spain)", - "ka": "Georgian", - "ka-GE": "Georgian (Georgia)", - "de": "German", - "de-AT": "German (Austria)", - "de-DE": "German (Germany)", - "de-LI": "German (Liechtenstein)", - "de-LU": "German (Luxembourg)", - "de-CH": "German (Switzerland)", - "el": "Greek", - "el-GR": "Greek (Greece)", - "gu": "Gujarati", - "gu-IN": "Gujarati (India)", - "he": "Hebrew", - "he-IL": "Hebrew (Israel)", - "hi": "Hindi", - "hi-IN": "Hindi (India)", - "hu": "Hungarian", - "hu-HU": "Hungarian (Hungary)", - "is": "Icelandic", - "is-IS": "Icelandic (Iceland)", - "id": "Indonesian", - "id-ID": "Indonesian (Indonesia)", - "it": "Italian", - "it-IT": "Italian (Italy)", - "it-CH": "Italian (Switzerland)", - "ja": "Japanese", - "ja-JP": "Japanese (Japan)", - "kn": "Kannada", - "kn-IN": "Kannada (India)", - "kk": "Kazakh", - "kk-KZ": "Kazakh (Kazakhstan)", - "kok": "Konkani", - "kok-IN": "Konkani (India)", - "ko": "Korean", - "ko-KR": "Korean (Korea)", - "ky": "Kyrgyz", - "ky-KG": "Kyrgyz (Kyrgyzstan)", - "lv": "Latvian", - "lv-LV": "Latvian (Latvia)", - "lt": "Lithuanian", - "lt-LT": "Lithuanian (Lithuania)", - "ms": "Malay", - "ms-BN": "Malay (Brunei Darussalam)", - "ms-MY": "Malay (Malaysia)", - "mt": "Maltese", - "mt-MT": "Maltese (Malta)", - "mi": "Maori", - "mi-NZ": "Maori (New Zealand)", - "mr": "Marathi", - "mr-IN": "Marathi (India)", - "mn": "Mongolian", - "mn-MN": "Mongolian (Mongolia)", - "ns": "Northern Sotho", - "ns-ZA": "Northern Sotho (South Africa)", - "nb": "Norwegian (Bokm?l)", - "nb-NO": "Norwegian (Bokm?l) (Norway)", - "nn-NO": "Norwegian (Nynorsk) (Norway)", - "ps": "Pashto", - "ps-AR": "Pashto (Afghanistan)", - "pl": "Polish", - "pl-PL": "Polish (Poland)", - "pt": "Portuguese", - "pt-BR": "Portuguese (Brazil)", - "pt-PT": "Portuguese (Portugal)", - "pa": "Punjabi", - "pa-IN": "Punjabi (India)", - "qu": "Quechua", - "qu-BO": "Quechua (Bolivia)", - "qu-EC": "Quechua (Ecuador)", - "qu-PE": "Quechua (Peru)", - "ro": "Romanian", - "ro-RO": "Romanian (Romania)", - "ru": "Russian", - "ru-RU": "Russian (Russia)", - "se": "Sami (Northern)", - "se-FI": "Sami (Inari) (Finland)", - "se-NO": "Sami (Southern) (Norway)", - "se-SE": "Sami (Southern) (Sweden)", - "sa": "Sanskrit", - "sa-IN": "Sanskrit (India)", - "sr-BA": "Serbian (Cyrillic) (Bosnia and Herzegovina)", - "sr-SP": "Serbian (Cyrillic) (Serbia and Montenegro)", - "sk": "Slovak", - "sk-SK": "Slovak (Slovakia)", - "sl": "Slovenian", - "sl-SI": "Slovenian (Slovenia)", - "es": "Spanish", - "es-AR": "Spanish (Argentina)", - "es-BO": "Spanish (Bolivia)", - "es-CL": "Spanish (Chile)", - "es-CO": "Spanish (Colombia)", - "es-CR": "Spanish (Costa Rica)", - "es-DO": "Spanish (Dominican Republic)", - "es-EC": "Spanish (Ecuador)", - "es-SV": "Spanish (El Salvador)", - "es-GT": "Spanish (Guatemala)", - "es-HN": "Spanish (Honduras)", - "es-MX": "Spanish (Mexico)", - "es-NI": "Spanish (Nicaragua)", - "es-PA": "Spanish (Panama)", - "es-PY": "Spanish (Paraguay)", - "es-PE": "Spanish (Peru)", - "es-PR": "Spanish (Puerto Rico)", - "es-ES": "Spanish (Spain)", - "es-UY": "Spanish (Uruguay)", - "es-VE": "Spanish (Venezuela)", - "sw": "Swahili", - "sw-KE": "Swahili (Kenya)", - "sv": "Swedish", - "sv-FI": "Swedish (Finland)", - "sv-SE": "Swedish (Sweden)", - "syr": "Syriac", - "syr-SY": "Syriac (Syria)", - "tl": "Tagalog", - "tl-PH": "Tagalog (Philippines)", - "ta": "Tamil", - "ta-IN": "Tamil (India)", - "tt": "Tatar", - "tt-RU": "Tatar (Russia)", - "te": "Telugu", - "te-IN": "Telugu (India)", - "th": "Thai", - "th-TH": "Thai (Thailand)", - "ts": "Tsonga", - "tn": "Tswana", - "tn-ZA": "Tswana (South Africa)", - "tr": "Turkish", - "tr-TR": "Turkish (Turkey)", - "uk": "Ukrainian", - "uk-UA": "Ukrainian (Ukraine)", - "ur": "Urdu", - "ur-PK": "Urdu (Islamic Republic of Pakistan)", - "uz": "Uzbek (Latin)", - "uz-UZ": "Uzbek (Cyrillic) (Uzbekistan)", - "vi": "Vietnamese", - "vi-VN": "Vietnamese (Viet Nam)", - "cy": "Welsh", - "cy-GB": "Welsh (United Kingdom)", - "xh": "Xhosa", - "xh-ZA": "Xhosa (South Africa)", - "zu": "Zulu", - "zu-ZA": "Zulu (South Africa)" -} diff --git a/extensions/core/interfaces/language/meta.json b/extensions/core/interfaces/language/meta.json deleted file mode 100644 index 65af3965d3..0000000000 --- a/extensions/core/interfaces/language/meta.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "$t:input", - "version": "1.0.0", - "icon": "translate", - "types": ["string", "lang"], - "recommended": { - "length": 10 - }, - "options": { - "limit": { - "name": "$t:limit", - "comment": "$t:limit_comment", - "interface": "toggle", - "default": false - } - }, - "translation": { - "en-US": { - "input": "Language", - "select_language": "Select a language...", - "limit": "Limit to Directus Availability", - "limit_comment": "Only show languages that are available as translations in Directus" - } - } -} diff --git a/extensions/core/interfaces/many-to-many/display.vue b/extensions/core/interfaces/many-to-many/display.vue deleted file mode 100644 index f2961f25e7..0000000000 --- a/extensions/core/interfaces/many-to-many/display.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/many-to-many/input.vue b/extensions/core/interfaces/many-to-many/input.vue deleted file mode 100644 index 0a12544d18..0000000000 --- a/extensions/core/interfaces/many-to-many/input.vue +++ /dev/null @@ -1,636 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/many-to-many/meta.json b/extensions/core/interfaces/many-to-many/meta.json deleted file mode 100644 index b7934da5c4..0000000000 --- a/extensions/core/interfaces/many-to-many/meta.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "$t:m2m", - "version": "1.0.0", - "types": ["o2m"], - "relation": "m2m", - "icon": "compare_arrows", - "options": { - "fields": { - "name": "$t:visible_columns", - "comment": "$t:visible_columns_comment", - "interface": "text-input", - "placeholder": "name,description" - }, - "preferences": { - "name": "$t:preferences", - "comment": "$t:preferences_comment", - "interface": "code", - "options": { - "language": "application/json", - "template": { - "viewType": "tabular", - "viewQuery": { - "fields": ["id", "name"] - }, - "filters": [ - { - "field": "name", - "operator": "contains", - "value": "hi" - } - ] - } - } - }, - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "options": { - "placeholder": "$t:template_placeholder" - } - } - }, - "translation": { - "en-US": { - "m2m": "Many to Many", - "visible_columns": "Visible Columns", - "visible_columns_comment": "Add a CSV of columns you want to display as preview", - "preferences": "Listing View Preferences", - "preferences_comment": "Set what options to use for the modal", - "relation_not_setup": "The relationship hasn't been configured correctly", - "template": "Display Template", - "template_comment": "Choose how to display values on the item layouts", - "template_placeholder": "{{movie.name}} — {{member.first_name}}" - } - } -} diff --git a/extensions/core/interfaces/many-to-one/display.vue b/extensions/core/interfaces/many-to-one/display.vue deleted file mode 100644 index 271cba2cce..0000000000 --- a/extensions/core/interfaces/many-to-one/display.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/extensions/core/interfaces/many-to-one/input.vue b/extensions/core/interfaces/many-to-one/input.vue deleted file mode 100644 index d352f0f1b5..0000000000 --- a/extensions/core/interfaces/many-to-one/input.vue +++ /dev/null @@ -1,345 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/many-to-one/meta.json b/extensions/core/interfaces/many-to-one/meta.json deleted file mode 100644 index 852ff17767..0000000000 --- a/extensions/core/interfaces/many-to-one/meta.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "$t:m2o", - "version": "1.0.1", - "types": ["m2o"], - "relation": "m2o", - "icon": "call_merge", - "options": { - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "options": { - "placeholder": "$t:template_placeholder" - } - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200, - "default": "$t:select_one" - }, - "threshold": { - "name": "$t:threshold", - "comment": "$t:threshold_comment", - "interface": "numeric", - "default": 20 - }, - "preferences": { - "name": "$t:preferences", - "comment": "$t:preferences_comment", - "interface": "code", - "options": { - "language": "application/json", - "template": { - "viewType": "tabular", - "viewQuery": { - "fields": ["id", "name"] - }, - "filters": [ - { - "field": "name", - "operator": "contains", - "value": "hi" - } - ] - } - } - }, - "icon": { - "name": "$t:icon", - "comment": "$t:icon_comment", - "interface": "icon", - "advanced": true - } - }, - "translation": { - "en-US": { - "m2o": "Many to One", - "template": "Dropdown Template", - "template_comment": "How to format the dropdown options", - "template_placeholder": "{{title}} — {{author}}", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "preferences": "Listing View Preferences", - "preferences_comment": "Set what options to use for the modal", - "relationship_not_setup": "The relationship hasn't been configured correctly", - "icon": "Icon", - "icon_comment": "Choose an optional icon to display on the left of the input", - "select_one": "Select one", - "threshold": "Threshold", - "threshold_comment": "The amount of items after which the interface will render a modal instead of a dropdown" - } - } -} diff --git a/extensions/core/interfaces/map/display.vue b/extensions/core/interfaces/map/display.vue deleted file mode 100644 index 6b351cf811..0000000000 --- a/extensions/core/interfaces/map/display.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - diff --git a/extensions/core/interfaces/map/input.vue b/extensions/core/interfaces/map/input.vue deleted file mode 100644 index 0bfa5d9243..0000000000 --- a/extensions/core/interfaces/map/input.vue +++ /dev/null @@ -1,443 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/map/leaflet.css b/extensions/core/interfaces/map/leaflet.css deleted file mode 100644 index 270195a415..0000000000 --- a/extensions/core/interfaces/map/leaflet.css +++ /dev/null @@ -1,227 +0,0 @@ - -/* Until we figure out why the controls are hidden */ -/* .leaflet-control-attribution { - pointer-events: none; -} */ - -.leaflet-map-pane { - z-index: -1 !important; -} - -.leaflet-control-container { - z-index: 1; -} - -.leaflet-control-attribution { - position: absolute; - right: 4px; - bottom: 4px; - color: var(--light-gray); -} - -.leaflet-control-zoom { - position: absolute; - left: 20px; - top: 70px; -} - -.leaflet-control-zoom-in, -.leaflet-control-zoom-out { - display: block; - transition: var(--fast) var(--transition) color; - height: 40px; - width: 40px; - color: var(--light-gray); - box-shadow: var(--box-shadow); - background: #fff; - text-decoration: none; - font-size: 24px; - font-weight: 300; - padding: 4px; - text-align: center; -} - -.leaflet-control-zoom-in:hover, -.leaflet-control-zoom-out:hover { - color: var(--accent); -} - -.leaflet-control-zoom-in { - border-radius: var(--border-radius) var(--border-radius) 0 0; - border-bottom: 1px solid var(--lightest-gray); -} - -.leaflet-control-zoom-out { - border-radius: 0 0 var(--border-radius) var(--border-radius); -} - -/* required styles */ - -.leaflet-pane, -.leaflet-tile, -.leaflet-marker-icon, -.leaflet-marker-shadow, -.leaflet-tile-container, -.leaflet-pane > svg, -.leaflet-pane > canvas, -.leaflet-zoom-box, -.leaflet-image-layer, -.leaflet-layer { - position: absolute; - left: 0; - top: 0; -} - -.leaflet-container { - overflow: hidden; -} - -.leaflet-tile, -.leaflet-marker-icon, -.leaflet-marker-shadow { - user-select: none; - -webkit-user-drag: none; -} - -/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ -.leaflet-safari .leaflet-tile { - image-rendering: -webkit-optimize-contrast; -} - -/* hack that prevents hw layers "stretching" when loading new tiles */ -.leaflet-safari .leaflet-tile-container { - width: 1600px; - height: 1600px; - -webkit-transform-origin: 0 0; -} - -.leaflet-marker-icon, -.leaflet-marker-shadow { - display: block; -} - -/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ -/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ -.leaflet-container .leaflet-overlay-pane svg, -.leaflet-container .leaflet-marker-pane img, -.leaflet-container .leaflet-shadow-pane img, -.leaflet-container .leaflet-tile-pane img, -.leaflet-container img.leaflet-image-layer, -.leaflet-container .leaflet-tile { - max-width: none !important; - max-height: none !important; -} - -.leaflet-container.leaflet-touch-zoom { - touch-action: pan-x pan-y; -} - -.leaflet-container.leaflet-touch-drag { - touch-action: none; - touch-action: pinch-zoom; -} - -.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { - touch-action: none; -} - -.leaflet-container { - -webkit-tap-highlight-color: transparent; -} - -.leaflet-container a { - -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); -} - -.leaflet-tile { - filter: inherit; - visibility: hidden; -} - -.leaflet-tile-loaded { - visibility: inherit; -} - -.leaflet-zoom-box { - width: 0; - height: 0; - box-sizing: border-box; - z-index: 800; -} - -/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ -.leaflet-overlay-pane svg { - -moz-user-select: none; -} - -.leaflet-pane { z-index: 400; } - -.leaflet-tile-pane { z-index: 200; } -.leaflet-overlay-pane { z-index: 400; } -.leaflet-shadow-pane { z-index: 500; } -.leaflet-marker-pane { z-index: 600; } -.leaflet-tooltip-pane { z-index: 650; } -.leaflet-popup-pane { z-index: 700; } - -.leaflet-map-pane canvas { z-index: 100; } -.leaflet-map-pane svg { z-index: 200; } - -.leaflet-vml-shape { - width: 1px; - height: 1px; -} - -.lvml { - behavior: url(#default#VML); - display: inline-block; - position: absolute; -} - -/* cursors */ - -.leaflet-interactive { - cursor: pointer; -} - -.leaflet-grab { - cursor: -webkit-grab; - cursor: -moz-grab; - cursor: grab; -} - -.leaflet-crosshair, -.leaflet-crosshair .leaflet-interactive { - cursor: crosshair; -} - -.leaflet-popup-pane, -.leaflet-control { - cursor: auto; -} - -.leaflet-dragging .leaflet-grab, -.leaflet-dragging .leaflet-grab .leaflet-interactive, -.leaflet-dragging .leaflet-marker-draggable { - cursor: move; - cursor: -webkit-grabbing; - cursor: -moz-grabbing; - cursor: grabbing; -} - -/* marker & overlays interactivity */ -.leaflet-marker-icon, -.leaflet-marker-shadow, -.leaflet-image-layer, -.leaflet-pane > svg path, -.leaflet-tile-container { - pointer-events: none; -} - -.leaflet-marker-icon.leaflet-interactive, -.leaflet-image-layer.leaflet-interactive, -.leaflet-pane > svg path.leaflet-interactive { - pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ - pointer-events: auto; -} - - diff --git a/extensions/core/interfaces/map/meta.json b/extensions/core/interfaces/map/meta.json deleted file mode 100644 index bc4c771366..0000000000 --- a/extensions/core/interfaces/map/meta.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "name": "$t:map", - "version": "1.0.1", - "types": ["json"], - "fieldset": true, - "icon": "place", - "options": { - "height": { - "name": "$t:height", - "interface": "text-input", - "default": 400 - }, - "mapLat": { - "name": "$t:map_lat", - "comment": "$t:map_lat_comment", - "interface": "text-input", - "default": 40.72803624 - }, - "mapLng": { - "name": "$t:map_lng", - "comment": "$t:map_lng_comment", - "interface": "text-input", - "default": -73.948963880 - }, - "defaultZoom": { - "name": "$t:default_zoom", - "comment": "$t:default_zoom_comment", - "interface": "text-input", - "default": 12 - }, - "maxZoom": { - "name": "$t:max_zoom", - "comment": "$t:max_zoom_comment", - "interface": "text-input", - "default": 17 - }, - "address_to_code": { - "name": "$t:address_to_code", - "comment": "$t:address_to_code_comment", - "interface": "toggle", - "type": "BOOLEAN", - "default": false - }, - "theme": { - "name": "$t:theme", - "comment": "$t:theme_comment", - "interface": "button-group", - "type": "JSON", - "default": "https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png", - "options": { - "choices": [ - { - "label": "Grayscale", - "value": "https://{s}.basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}.png" - }, - { - "label": "Color", - "value": "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png" - } - ] - } - } - }, - "translation": { - "en-US": { - "map": "Map", - "choices": "choices", - "choices_comment": "Enter JSON key value pairs with the saved value and text displayed.", - "theme": "Interface Theme", - "theme_comment": "Set the UI of interface if supported", - "value": "Value", - "map_lat": "Default Latitude", - "map_lat_comment": "Map will be centered at this latitude", - "map_lng": "Default Longitude", - "map_lng_comment": "Map will be centered at this longitude", - "height": "Height", - "default_zoom": "Default Zoom", - "default_zoom_comment": "Default zoom level of the map", - "max_zoom": "Max Zoom", - "max_zoom_comment": "Maximum zoom allowed in the map", - "no_location": "No location found", - "user_location_error_blocked": "You've disabled the location access. Kindly enable it from the browser addressbar to auto detect your location.", - "user_location_error": "There was an error while trying to get your location. Plese try again.", - "address_to_code": "Address Input", - "address_to_code_comment": "Add an input field to automatically get the geocodes from an address. Uses Nominatim. Please check their usage policy.", - "address_to_code_error": "No geocode found for this address" - } - } -} diff --git a/extensions/core/interfaces/map/package.json b/extensions/core/interfaces/map/package.json deleted file mode 100644 index 0a058cde3c..0000000000 --- a/extensions/core/interfaces/map/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@directus/map", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Harsh Kansagara ", - "license": "GPL-3.0", - "dependencies": { - "leaflet": "^1.3.4" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/interfaces/markdown/demo.md b/extensions/core/interfaces/markdown/demo.md deleted file mode 100644 index af45f9d930..0000000000 --- a/extensions/core/interfaces/markdown/demo.md +++ /dev/null @@ -1,132 +0,0 @@ -# h1 Heading -## h2 Heading -### h3 Heading -#### h4 Heading -##### h5 Heading -###### h6 Heading - - -## Horizontal Rules - -___ - ---- - -*** - - -## Emphasis - -**This is bold text** - -__This is bold text__ - -*This is italic text* - -_This is italic text_ - -~~Strikethrough~~ - - -## Blockquotes - - -> Blockquotes can also be nested... ->> ...by using additional greater-than signs right next to each other... -> > > ...or with spaces between arrows. - - -## Lists - -Unordered - -+ Create a list by starting a line with `+`, `-`, or `*` -+ Sub-lists are made by indenting 2 spaces: - - Marker character change forces new list start: - * Ac tristique libero volutpat at - + Facilisis in pretium nisl aliquet - - Nulla volutpat aliquam velit -+ Very easy! - -Ordered - -1. Lorem ipsum dolor sit amet -2. Consectetur adipiscing elit -3. Integer molestie lorem at massa - - -1. You can use sequential numbers... -1. ...or keep all the numbers as `1.` - -Start numbering with offset: - -57. foo -1. bar - - -## Code - -Inline `code` - -Indented code - - // Some comments - line 1 of code - line 2 of code - line 3 of code - - -Block code "fences" - -``` -Sample text here... -``` - -Syntax highlighting - -``` js -var foo = function (bar) { - return bar++; -}; - -console.log(foo(5)); -``` - -## Tables - -| Option | Description | -| ------ | ----------- | -| data | path to data files to supply the data that will be passed into templates. | -| engine | engine to be used for processing templates. Handlebars is the default. | -| ext | extension to be used for dest files. | - -Right aligned columns - -| Option | Description | -| ------:| -----------:| -| data | path to data files to supply the data that will be passed into templates. | -| engine | engine to be used for processing templates. Handlebars is the default. | -| ext | extension to be used for dest files. | - - -## Links - -[link text](http://dev.nodeca.com) - -[link with title](http://nodeca.github.io/pica/demo/ "title text!") - -Autoconverted link https://github.com/nodeca/pica (enable linkify to see) - - -## Images - -![Minion](https://octodex.github.com/images/minion.png) -![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") - -Like links, Images also have a footnote style syntax - -![Alt text][id] - -With a reference later in the document defining the URL location: - -[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" diff --git a/extensions/core/interfaces/markdown/display.vue b/extensions/core/interfaces/markdown/display.vue deleted file mode 100644 index 8dc2f852c5..0000000000 --- a/extensions/core/interfaces/markdown/display.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/extensions/core/interfaces/markdown/input.vue b/extensions/core/interfaces/markdown/input.vue deleted file mode 100644 index 3248226d45..0000000000 --- a/extensions/core/interfaces/markdown/input.vue +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - - diff --git a/extensions/core/interfaces/markdown/meta.json b/extensions/core/interfaces/markdown/meta.json deleted file mode 100644 index ddab54c0e1..0000000000 --- a/extensions/core/interfaces/markdown/meta.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "$t:markdown", - "version": "1.0.0", - "types": ["string"], - "icon": "text_fields", - "recommended": { - "length": 65534 - }, - "options": { - "rows": { - "name": "$t:rows", - "comment": "$t:rows_comment", - "interface": "numeric", - "options": { - "min": 5, - "max": 100 - }, - "default": 12 - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "textarea", - "default": "Enter **markdown** here...", - "placeholder": "Enter **markdown** here..." - } - }, - "translation": { - "en-US": { - "markdown": "Markdown", - "rows": "Rows", - "rows_comment": "The starting number of text rows available", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text" - } - } -} diff --git a/extensions/core/interfaces/markdown/package.json b/extensions/core/interfaces/markdown/package.json deleted file mode 100644 index 1c712306e1..0000000000 --- a/extensions/core/interfaces/markdown/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@directus/markdown", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "GPL-3.0", - "dependencies": { - "marked": "^0.3.19", - "vue": "^2.5.16", - "vue-hot-reload-api": "^2.3.0" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/interfaces/multiselect/display.vue b/extensions/core/interfaces/multiselect/display.vue deleted file mode 100644 index 3adf064bc6..0000000000 --- a/extensions/core/interfaces/multiselect/display.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/extensions/core/interfaces/multiselect/input.vue b/extensions/core/interfaces/multiselect/input.vue deleted file mode 100644 index 9e4a53a9de..0000000000 --- a/extensions/core/interfaces/multiselect/input.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/multiselect/meta.json b/extensions/core/interfaces/multiselect/meta.json deleted file mode 100644 index fc0419fe9a..0000000000 --- a/extensions/core/interfaces/multiselect/meta.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "$t:multiselect", - "version": "1.0.1", - "types": ["array"], - "icon": "playlist_add_check", - "recommended": { - "length": 100 - }, - "options": { - "choices": { - "name": "$t:choices", - "comment": "$t:choices_comment", - "interface": "code", - "default": { - "value1": "$t:option 1", - "value2": "$t:option 2", - "value3": "$t:option 3", - "value4": "$t:option 4", - "value5": "$t:option 5" - } - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200 - }, - "wrapWithDelimiter": { - "name": "$t:wrap", - "comment": "$t:wrap_comment", - "interface": "toggle", - "default": true - }, - "formatting": { - "name": "$t:format", - "comment": "$t:format_comment", - "interface": "radio-buttons", - "default": "text", - "options": { - "choices": { - "text": "Display Text", - "value": "Value" - } - } - } - }, - "translation": { - "en-US": { - "multiselect": "Multi-Select", - "choices": "Choices", - "choices_comment": "Enter JSON key value pairs with the saved value and displayed text", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "option": "Option", - "wrap": "Wrap with Delimiter", - "wrap_comment": "Wrap the values with a pair of delimiters to allow strict searching for a single value", - "format": "Browse Format", - "format_comment": "The output format on the Browse Items page" - } - } -} diff --git a/extensions/core/interfaces/numeric/display.vue b/extensions/core/interfaces/numeric/display.vue deleted file mode 100644 index d2cba9b351..0000000000 --- a/extensions/core/interfaces/numeric/display.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/extensions/core/interfaces/numeric/input.vue b/extensions/core/interfaces/numeric/input.vue deleted file mode 100644 index fc30ec5f58..0000000000 --- a/extensions/core/interfaces/numeric/input.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/numeric/meta.json b/extensions/core/interfaces/numeric/meta.json deleted file mode 100644 index 39d652b9c5..0000000000 --- a/extensions/core/interfaces/numeric/meta.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "$t:numeric", - "version": "1.0.1", - "types": ["integer", "decimal"], - "icon": "dialpad", - "recommended": { - "length": 10 - }, - "options": { - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 100 - }, - "localized": { - "name": "$t:localized", - "comment": "$t:localized_comment", - "interface": "toggle", - "default": true - }, - "iconLeft": { - "name": "$t:icon_left", - "comment": "$t:icon_left_comment", - "interface": "icon", - "advanced": true - }, - "iconRight": { - "name": "$t:icon_right", - "comment": "$t:icon_right_comment", - "interface": "icon", - "advanced": true - } - }, - "translation": { - "en-US": { - "numeric": "Numeric", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "localized": "Localized", - "localized_comment": "Localize the output to the user's locale", - "icon_left": "Icon Left", - "icon_left_comment": "Choose an optional icon to display on the left of the input", - "icon_right": "Icon Right", - "icon_right_comment": "Choose an optional icon to display on the right of the input" - } - } -} diff --git a/extensions/core/interfaces/one-to-many/display.vue b/extensions/core/interfaces/one-to-many/display.vue deleted file mode 100644 index 30bf9dc981..0000000000 --- a/extensions/core/interfaces/one-to-many/display.vue +++ /dev/null @@ -1,48 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/one-to-many/input.vue b/extensions/core/interfaces/one-to-many/input.vue deleted file mode 100644 index e8ac72a813..0000000000 --- a/extensions/core/interfaces/one-to-many/input.vue +++ /dev/null @@ -1,561 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/one-to-many/meta.json b/extensions/core/interfaces/one-to-many/meta.json deleted file mode 100644 index c88ae64ba0..0000000000 --- a/extensions/core/interfaces/one-to-many/meta.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "$t:o2m", - "version": "2.0.0", - "types": ["o2m"], - "options": { - "fields": { - "name": "$t:visible_columns", - "comment": "$t:visible_columns_comment", - "interface": "text-input", - "placeholder": "name,description" - }, - "preferences": { - "name": "$t:preferences", - "comment": "$t:preferences_comment", - "interface": "code", - "options": { - "language": "application/json", - "template": { - "viewType": "tabular", - "viewQuery": { - "fields": ["id", "name"] - }, - "filters": [ - { - "field": "name", - "operator": "contains", - "value": "hi" - } - ] - } - } - }, - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "options": { - "placeholder": "$t:template_placeholder" - } - } - }, - "relation": "o2m", - "icon": "call_split", - "translation": { - "en-US": { - "o2m": "One to Many", - "select_items": "Select the items", - "relation_not_setup": "The relationship hasn't been configured correctly", - "visible_columns": "Visible Columns", - "visible_columns_comment": "Add a CSV of columns you want to display as preview", - "preferences": "Listing View Preferences", - "preferences_comment": "Set what options to use for the modal", - "template": "Dropdown Template", - "template_comment": "How to format the dropdown options", - "template_placeholder": "{{title}} — {{author}}" - } - } -} diff --git a/extensions/core/interfaces/password/display.vue b/extensions/core/interfaces/password/display.vue deleted file mode 100644 index 2ace4b1d7f..0000000000 --- a/extensions/core/interfaces/password/display.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/password/hooks.php b/extensions/core/interfaces/password/hooks.php deleted file mode 100644 index bc92ed21a6..0000000000 --- a/extensions/core/interfaces/password/hooks.php +++ /dev/null @@ -1,34 +0,0 @@ -getData(); - $container = Application::getInstance()->getContainer(); - $schemaManager = $container->get('schema_manager'); - $hashManager = $container->get('hash_manager'); - - $collection = $schemaManager->getCollection($payload->attribute('collection_name')); - $interfaceName = basename(__DIR__); - - foreach ($data as $fieldName => $value) { - $field = $collection->getField($fieldName); - if ($field && $field->getInterface() === $interfaceName) { - $options = $field->getOptions() ?: ['hasher' => 'core']; - - $hashedString = $hashManager->hash($value, $options); - $payload->set($fieldName, $hashedString); - } - } - - return $payload; -}; - -return [ - 'filters' => [ - 'item.create:before' => $hashValue, - 'item.update:before' => $hashValue, - ] -]; - diff --git a/extensions/core/interfaces/password/input.vue b/extensions/core/interfaces/password/input.vue deleted file mode 100644 index b4de8b8b7c..0000000000 --- a/extensions/core/interfaces/password/input.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/password/meta.json b/extensions/core/interfaces/password/meta.json deleted file mode 100644 index 7f8e3560b3..0000000000 --- a/extensions/core/interfaces/password/meta.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "$t:password", - "version": "1.0.1", - "types": ["string"], - "icon": "security", - "recommended": { - "length": 100 - }, - "options": { - "hide": { - "name": "$t:hide", - "comment": "$t:hide_comment", - "interface": "toggle", - "default": true - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 100, - "default": "Enter a password..." - }, - "showHash": { - "name": "$t:show_hash", - "comment": "$t:show_hash_comment", - "interface": "toggle", - "default": false - }, - "hashingType": { - "name": "$t:hashing_type", - "comment": "$t:hashing_type_comment", - "interface": "dropdown", - "default": "core", - "options": { - "choices": { - "core": "Default", - "bcrypt": "bcrypt", - "md5": "md5", - "sha1": "SHA-1", - "sha224": "SHA-224", - "sha256": "SHA-256", - "sha384": "SHA-384", - "sha512": "SHA-512" - } - } - } - }, - "translation": { - "en-US": { - "password": "Password", - "hide": "Hide Value", - "hide_comment": "Display dots instead of the characters you enter", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "confirm_placeholder": "Confirm password...", - "show_hash": "Show the hashed output", - "show_hash_comment": "Display the saved hash", - "hashing_type": "Hashing Type", - "hashing_type_comment": "What method of hashing to use" - } - } -} diff --git a/extensions/core/interfaces/preview/display.vue b/extensions/core/interfaces/preview/display.vue deleted file mode 100644 index 6cd8ffba2d..0000000000 --- a/extensions/core/interfaces/preview/display.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/extensions/core/interfaces/preview/input.vue b/extensions/core/interfaces/preview/input.vue deleted file mode 100644 index 9dc02d58cd..0000000000 --- a/extensions/core/interfaces/preview/input.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/preview/meta.json b/extensions/core/interfaces/preview/meta.json deleted file mode 100644 index fcaa85f196..0000000000 --- a/extensions/core/interfaces/preview/meta.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "$t:preview", - "version": "1.0.0", - "types": ["alias"], - "icon": "visibility", - "options": { - "url_template": { - "name": "$t:url_template", - "comment": "Test", - "interface": "text-input", - "required": true, - "default": "https://example.com/collection/{{ id }}", - "options": { - "placeholder": "https://example.com/articles/{{ id }}/{{ slug }}" - } - } - }, - "translation": { - "en-US": { - "preview": "Preview", - "url_template": "URL Template", - "url_template_comment": "A mustache template for a URL to preview content", - "preview_item": "Preview this item" - } - } -} diff --git a/extensions/core/interfaces/primary-key/display.vue b/extensions/core/interfaces/primary-key/display.vue deleted file mode 100644 index 0f5b90760d..0000000000 --- a/extensions/core/interfaces/primary-key/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/primary-key/input.vue b/extensions/core/interfaces/primary-key/input.vue deleted file mode 100644 index 3af18789f6..0000000000 --- a/extensions/core/interfaces/primary-key/input.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/primary-key/meta.json b/extensions/core/interfaces/primary-key/meta.json deleted file mode 100644 index a4eda48c3b..0000000000 --- a/extensions/core/interfaces/primary-key/meta.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "$t:primary_key", - "version": "1.0.1", - "types": ["integer", "string"], - "icon": "vpn_key", - "recommended": { - "length": 10 - }, - "options": {}, - "translation": { - "en-US": { - "primary_key": "Primary Key", - "immutable": "Can not be changed" - } - } -} diff --git a/extensions/core/interfaces/radio-buttons/display.vue b/extensions/core/interfaces/radio-buttons/display.vue deleted file mode 100644 index 9ac14050d6..0000000000 --- a/extensions/core/interfaces/radio-buttons/display.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/extensions/core/interfaces/radio-buttons/input.vue b/extensions/core/interfaces/radio-buttons/input.vue deleted file mode 100644 index 48a2456364..0000000000 --- a/extensions/core/interfaces/radio-buttons/input.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/radio-buttons/meta.json b/extensions/core/interfaces/radio-buttons/meta.json deleted file mode 100644 index 115d081731..0000000000 --- a/extensions/core/interfaces/radio-buttons/meta.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "$t:radio", - "version": "1.0.1", - "types": ["string"], - "fieldset": true, - "icon": "radio_button_checked", - "recommended": { - "length": 100 - }, - "options": { - "choices": { - "name": "$t:choices", - "comment": "$t:choices_comment", - "interface": "code", - "type": "JSON", - "default": { - "value1": "$t:option 1", - "value2": "$t:option 2", - "value3": "$t:option 3", - "value4": "$t:option 4", - "value5": "$t:option 5", - "value6": "$t:option 6", - "value7": "$t:option 7", - "value8": "$t:option 8" - } - }, - "format": { - "name": "$t:format", - "comment": "$t:format_comment", - "interface": "toggle", - "type": "BOOLEAN", - "default": true - } - }, - "translation": { - "en-US": { - "radio": "Radio Buttons", - "choices": "choices", - "choices_comment": "Enter JSON key value pairs with the saved value and text displayed.", - "option": "Option", - "format": "Browse Format", - "format_comment": "The output format on the Browse Items page" - } - } -} diff --git a/extensions/core/interfaces/rating/display.vue b/extensions/core/interfaces/rating/display.vue deleted file mode 100644 index cc18bcd99e..0000000000 --- a/extensions/core/interfaces/rating/display.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/rating/input.vue b/extensions/core/interfaces/rating/input.vue deleted file mode 100644 index 5c37d9e2e6..0000000000 --- a/extensions/core/interfaces/rating/input.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/rating/meta.json b/extensions/core/interfaces/rating/meta.json deleted file mode 100644 index a378b7c606..0000000000 --- a/extensions/core/interfaces/rating/meta.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "$t:rating", - "version": "1.0.1", - "types": ["integer", "decimal"], - "icon": "star", - "fieldset": true, - "recommended": { - "length": 10 - }, - "options": { - "active_color": { - "name": "$t:active_color", - "comment": "$t:active_color_comment", - "interface": "color-palette", - "default": "blue-grey-900" - }, - "max_stars": { - "name": "$t:max_stars", - "comment": "$t:max_stars_comment", - "interface": "numeric", - "default": 5 - }, - "display": { - "name": "$t:display", - "comment": "$t:display_comment", - "interface": "button-group", - "default": "number", - "type": "JSON", - "options": { - "choices": [ - { - "label": "Numbers", - "value": "number" - }, - { - "label": "Stars", - "value": "star" - } - ] - } - } - }, - "translation": { - "en-US": { - "rating": "Rating", - "value": "Value", - "active_color": "Active Color", - "active_color_comment": "Active color of selected stars", - "max_stars": "Max Stars", - "max_stars_comment": "Number of maximum rating allowed", - "display": "Display", - "display_comment": "How to display rating values" - } - } -} diff --git a/extensions/core/interfaces/rating/stars.vue b/extensions/core/interfaces/rating/stars.vue deleted file mode 100644 index ac69a5ac6e..0000000000 --- a/extensions/core/interfaces/rating/stars.vue +++ /dev/null @@ -1,151 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/slider/display.vue b/extensions/core/interfaces/slider/display.vue deleted file mode 100644 index 0ac68b3513..0000000000 --- a/extensions/core/interfaces/slider/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/slider/input.vue b/extensions/core/interfaces/slider/input.vue deleted file mode 100644 index eaeb3b5010..0000000000 --- a/extensions/core/interfaces/slider/input.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/slider/meta.json b/extensions/core/interfaces/slider/meta.json deleted file mode 100644 index 23255d2a37..0000000000 --- a/extensions/core/interfaces/slider/meta.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "$t:slider", - "version": "1.0.1", - "types": ["integer"], - "icon": "tune", - "recommended": { - "length": 10 - }, - "options": { - "minimum": { - "name": "$t:min", - "comment": "$t:min_comment", - "interface": "numeric", - "default": 0 - }, - "maximum": { - "name": "$t:max", - "interface": "numeric", - "comment": "$t:max_comment", - "default": 100 - }, - "step": { - "name": "$t:step", - "comment": "$t:step_comment", - "interface": "numeric", - "default": 1 - }, - "unit": { - "name": "$t:unit", - "comment": "$t:unit_comment", - "interface": "text-input" - } - }, - "translation": { - "en-US": { - "slider": "Slider", - "min": "Minimum", - "min_comment": "The minimum valid value", - "max": "Maximum", - "max_comment": "The maximum valid value", - "step": "Step", - "step_comment": "Increments at which the value can be set", - "unit": "Unit", - "unit_comment": "Show an unit next to the slider value, e.g. 15 Pounds" - } - } -} diff --git a/extensions/core/interfaces/slug/display.vue b/extensions/core/interfaces/slug/display.vue deleted file mode 100644 index 0f5b90760d..0000000000 --- a/extensions/core/interfaces/slug/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/slug/input.vue b/extensions/core/interfaces/slug/input.vue deleted file mode 100644 index 8e0c977fff..0000000000 --- a/extensions/core/interfaces/slug/input.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/slug/meta.json b/extensions/core/interfaces/slug/meta.json deleted file mode 100644 index 20d5b7aec3..0000000000 --- a/extensions/core/interfaces/slug/meta.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "$t:slug", - "version": "1.0.2", - "types": ["string"], - "icon": "link", - "recommended": { - "length": 200 - }, - "options": { - "placeholder": { - "name": "$t:placeholder_name", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200, - "default": "A unique label..." - }, - "forceLowercase": { - "name": "$t:force_lowercase", - "comment": "$t:force_lowercase_comment", - "interface": "toggle", - "default": true - }, - "mirroredField": { - "name": "$t:mirrored_field", - "comment": "$t:mirrored_field_comment", - "interface": "text-input" - } - }, - "translation": { - "en-US": { - "slug": "Slug", - "placeholder_name": "Placeholder", - "placeholder_comment": "The placeholder text to show", - "force_lowercase": "Force Lowercase", - "force_lowercase_comment": "Makes sure the slug is in lowercase", - "mirrored_field": "Mirrored Field", - "mirrored_field_comment": "Keep the slug up to date with another (text) field" - } - } -} diff --git a/extensions/core/interfaces/slug/package.json b/extensions/core/interfaces/slug/package.json deleted file mode 100644 index 81085b8c1f..0000000000 --- a/extensions/core/interfaces/slug/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@directus/slug", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "Rijk van Zanten ", - "license": "GPL-3.0", - "dependencies": { - "slugify": "^1.3.1" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/interfaces/sort/display.vue b/extensions/core/interfaces/sort/display.vue deleted file mode 100644 index 0f5b90760d..0000000000 --- a/extensions/core/interfaces/sort/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/sort/input.vue b/extensions/core/interfaces/sort/input.vue deleted file mode 100644 index 067e1c6e29..0000000000 --- a/extensions/core/interfaces/sort/input.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/sort/meta.json b/extensions/core/interfaces/sort/meta.json deleted file mode 100644 index bfa4c524c6..0000000000 --- a/extensions/core/interfaces/sort/meta.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "$t:sort", - "version": "1.0.1", - "types": ["sort"], - "icon": "low_priority", - "recommended": { - "length": 10 - }, - "options": {}, - "translation": { - "en-US": { - "sort": "Sort" - } - } -} diff --git a/extensions/core/interfaces/status/display.vue b/extensions/core/interfaces/status/display.vue deleted file mode 100644 index c7ff7a5638..0000000000 --- a/extensions/core/interfaces/status/display.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/status/input.vue b/extensions/core/interfaces/status/input.vue deleted file mode 100644 index 1d120afc4a..0000000000 --- a/extensions/core/interfaces/status/input.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/status/meta.json b/extensions/core/interfaces/status/meta.json deleted file mode 100644 index b8b4b4d020..0000000000 --- a/extensions/core/interfaces/status/meta.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "name": "$t:status", - "version": "1.1.0", - "types": ["status"], - "recommended": { - "defaultValue": "draft", - "length": 20 - }, - "fieldset": true, - "icon": "outlined_flag", - "options": { - "simpleBadge": { - "name": "$t:simple_badge", - "comment": "$t:simple_badge_comment", - "interface": "toggle", - "type": "BOOLEAN", - "default": true - }, - "status_mapping": { - "name": "$t:status_mapping", - "comment": "$t:status_mapping_comment", - "interface": "code", - "type": "JSON", - "options": { - "language": "application/json", - "template": { - "published": { - "name": "$t:published", - "text_color": "white", - "background_color": "accent", - "browse_subdued": false, - "browse_badge": true, - "soft_delete": false, - "published": true - }, - "under-review": { - "name": "$t:under_review", - "text_color": "white", - "background_color": "amber", - "browse_subdued": true, - "browse_badge": true, - "soft_delete": false, - "published": false - }, - "draft": { - "name": "$t:draft", - "text_color": "white", - "background_color": "blue-grey-200", - "browse_subdued": true, - "browse_badge": true, - "soft_delete": false, - "published": false - }, - "deleted": { - "name": "$t:deleted", - "text_color": "white", - "background_color": "red", - "browse_subdued": true, - "browse_badge": true, - "soft_delete": true, - "published": false - } - } - }, - "default": { - "published": { - "name": "$t:published", - "text_color": "white", - "background_color": "accent", - "browse_subdued": false, - "browse_badge": true, - "soft_delete": false, - "published": true - }, - "draft": { - "name": "$t:draft", - "text_color": "white", - "background_color": "blue-grey-200", - "browse_subdued": true, - "browse_badge": true, - "soft_delete": false, - "published": false - }, - "deleted": { - "name": "$t:deleted", - "text_color": "white", - "background_color": "red", - "browse_subdued": true, - "browse_badge": true, - "soft_delete": true, - "published": false - } - } - } - }, - "translation": { - "en-US": { - "status": "Status", - "status_mapping": "Status Mapping", - "status_mapping_comment": "Enter JSON status options", - "simple_badge": "Simple Badge", - "simple_badge_comment": - "Displays a colored dot on the item listing page.", - "published": "Published", - "under_review": "Under Review", - "draft": "Draft", - "deleted": "Deleted" - } - } -} diff --git a/extensions/core/interfaces/tags/display.vue b/extensions/core/interfaces/tags/display.vue deleted file mode 100644 index 6ba301c5b3..0000000000 --- a/extensions/core/interfaces/tags/display.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/tags/input.vue b/extensions/core/interfaces/tags/input.vue deleted file mode 100644 index d8ae09e07a..0000000000 --- a/extensions/core/interfaces/tags/input.vue +++ /dev/null @@ -1,161 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/tags/meta.json b/extensions/core/interfaces/tags/meta.json deleted file mode 100644 index 8ff468cdcd..0000000000 --- a/extensions/core/interfaces/tags/meta.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "$t:tags", - "version": "1.1.0", - "types": ["array", "string"], - "icon": "local_offer", - "recommended": { - "length": 2000 - }, - "options": { - "alphabetize": { - "name": "$t:alphabetize", - "comment": "$t:alphabetize_comment", - "interface": "toggle", - "default": true - }, - "lowercase": { - "name": "$t:lowercase", - "comment": "$t:lowercase_comment", - "interface": "toggle", - "default": true - }, - "wrap": { - "name": "$t:wrap", - "comment": "$t:wrap_comment", - "interface": "toggle", - "default": false - }, - "format": { - "name": "$t:format", - "comment": "$t:format_comment", - "interface": "toggle", - "default": false - }, - "sanitize": { - "name": "$t:sanitize", - "comment": "$t:sanitize_comment", - "interface": "toggle", - "default": false - }, - "iconLeft": { - "name": "$t:icon_left", - "comment": "$t:icon_left_comment", - "interface": "icon", - "advanced": true - }, - "iconRight": { - "name": "$t:icon_right", - "comment": "$t:icon_right_comment", - "interface": "icon", - "default": "local_offer", - "advanced": true - } - }, - "translation": { - "en-US": { - "tags": "Tags", - "alphabetize": "Alphabetize tags", - "alphabetize_comment": "Will rearrange tags to be alphabetical", - "lowercase": "Force Lowercase", - "lowercase_comment": "Convert all tags to lowercase", - "wrap": "Wrap with delimiter", - "wrap_comment": "Wrap the values with a pair of delimiters to allow strict searching for a single value", - "format": "Format Value", - "format_comment": "Convert the tags to Title Case when displaying the value", - "sanitize": "Sanitize", - "sanitize_comment": "Removes any non-alphanumeric characters and converts spaces to hyphens", - "placeholder_text": "Enter tag and then hit enter or comma...", - "icon_left": "Icon Left", - "icon_left_comment": "Choose an optional icon to display on the left of the input", - "icon_right": "Icon Right", - "icon_right_comment": "Choose an optional icon to display on the right of the input" - } - } -} diff --git a/extensions/core/interfaces/text-input/display.vue b/extensions/core/interfaces/text-input/display.vue deleted file mode 100644 index 804163defc..0000000000 --- a/extensions/core/interfaces/text-input/display.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/extensions/core/interfaces/text-input/input.vue b/extensions/core/interfaces/text-input/input.vue deleted file mode 100644 index b86e8b2b57..0000000000 --- a/extensions/core/interfaces/text-input/input.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/text-input/meta.json b/extensions/core/interfaces/text-input/meta.json deleted file mode 100644 index 250481b8b9..0000000000 --- a/extensions/core/interfaces/text-input/meta.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "$t:input", - "version": "1.0.1", - "icon": "text_fields", - "types": ["string", "lang"], - "recommended": { - "length": 200 - }, - "options": { - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200 - }, - "trim": { - "name": "$t:trim", - "comment": "$t:trim_comment", - "interface": "toggle", - "default": true - }, - "showCharacterCount": { - "name": "$t:char_count", - "comment": "$t:char_count_comment", - "interface": "toggle", - "default": true - }, - "iconLeft": { - "name": "$t:icon_left", - "comment": "$t:icon_left_comment", - "interface": "icon", - "advanced": true - }, - "iconRight": { - "name": "$t:icon_right", - "comment": "$t:icon_right_comment", - "interface": "icon", - "advanced": true - }, - "formatValue": { - "name": "$t:format", - "comment": "$t:format_comment", - "interface": "toggle", - "default": false - }, - "width": { - "name": "$t:width", - "comment": "$t:width_comment", - "interface": "dropdown", - "default": "auto", - "options": { - "choices": { - "auto": "$t:auto", - "small": "$t:small", - "medium": "$t:medium", - "large": "$t:large" - } - } - } - }, - "translation": { - "en-US": { - "input": "Text Input", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "trim": "Trim", - "trim_comment": "Trim surrounding whitespace from the value before saving", - "char_count": "Show Character Count", - "char_count_comment": "Show the remaining characters available next to the input", - "icon_left": "Icon Left", - "icon_left_comment": "Choose an optional icon to display on the left of the input", - "icon_right": "Icon Right", - "icon_right_comment": "Choose an optional icon to display on the right of the input", - "format": "Pretty Output", - "format_comment": "Convert the value to title case", - "width": "Size", - "width_comment": "Set what width to use for the input", - "auto": "Automatic", - "small": "Small", - "medium": "Medium", - "large": "Large" - } - } -} diff --git a/extensions/core/interfaces/textarea/display.vue b/extensions/core/interfaces/textarea/display.vue deleted file mode 100644 index 4acb0758f6..0000000000 --- a/extensions/core/interfaces/textarea/display.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/extensions/core/interfaces/textarea/input.vue b/extensions/core/interfaces/textarea/input.vue deleted file mode 100644 index a0df9ca816..0000000000 --- a/extensions/core/interfaces/textarea/input.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/textarea/meta.json b/extensions/core/interfaces/textarea/meta.json deleted file mode 100644 index 19ea677251..0000000000 --- a/extensions/core/interfaces/textarea/meta.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "$t:textarea", - "version": "1.0.0", - "types": ["string"], - "icon": "text_fields", - "recommended": { - "length": 2000 - }, - "options": { - "rows": { - "name": "$t:rows", - "comment": "$t:rows_comment", - "interface": "numeric", - "options": { - "min": 5, - "max": 100 - }, - "default": 12 - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200 - } - }, - "translation": { - "en-US": { - "textarea": "Text-Area", - "rows": "Rows", - "rows_comment": "The number of text rows available for the input before scrolling", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text" - } - } -} diff --git a/extensions/core/interfaces/time/display.vue b/extensions/core/interfaces/time/display.vue deleted file mode 100644 index 640d76cf2c..0000000000 --- a/extensions/core/interfaces/time/display.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - diff --git a/extensions/core/interfaces/time/input.vue b/extensions/core/interfaces/time/input.vue deleted file mode 100644 index b5663f08ca..0000000000 --- a/extensions/core/interfaces/time/input.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/time/meta.json b/extensions/core/interfaces/time/meta.json deleted file mode 100644 index 0595659cda..0000000000 --- a/extensions/core/interfaces/time/meta.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "$t:time", - "version": "1.0.0", - "types": ["time"], - "icon": "access_time", - "options": { - "display24HourClock": { - "name": "$t:24hour", - "comment": "$t:24hour_comment", - "interface": "toggle", - "default": true - } - }, - "translation": { - "en-US": { - "time": "Time", - "include_seconds": "Include seconds", - "include_seconds_comment": "Include seconds in the interface", - "24hour": "Display 24 hour clock", - "24hour_comment": "Show the time in 24-hour format (eg.: 15:30)" - } - } -} diff --git a/extensions/core/interfaces/toggle-icon/display.vue b/extensions/core/interfaces/toggle-icon/display.vue deleted file mode 100644 index 031944b9ae..0000000000 --- a/extensions/core/interfaces/toggle-icon/display.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/toggle-icon/input.vue b/extensions/core/interfaces/toggle-icon/input.vue deleted file mode 100644 index 8d67ae5bc9..0000000000 --- a/extensions/core/interfaces/toggle-icon/input.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/toggle-icon/meta.json b/extensions/core/interfaces/toggle-icon/meta.json deleted file mode 100644 index 20f955369a..0000000000 --- a/extensions/core/interfaces/toggle-icon/meta.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "$t:toggle-icon", - "version": "1.0.0", - "types": ["boolean"], - "icon": "favorite_border", - "options": { - "textInactive": { - "name": "$t:text-inactive-name", - "comment": "$t:text-inactive-comment", - "interface": "text-input", - "options": { - "placeholder": "$t:text-inactive-placeholder" - } - }, - "iconInactive": { - "name": "$t:icon-inactive-name", - "comment": "$t:icon-inactive-comment", - "default": "favorite_border", - "interface": "icon" - }, - "colorInactive": { - "name": "$t:color-inactive-name", - "comment": "$t:color-inactive-comment", - "default": "blue-grey", - "interface": "color-palette" - }, - "textActive": { - "name": "$t:text-active-name", - "comment": "$t:text-active-comment", - "interface": "text-input", - "options": { - "placeholder": "$t:text-active-placeholder" - } - }, - "iconActive": { - "name": "$t:icon-active-name", - "comment": "$t:icon-active-comment", - "default": "favorite", - "interface": "icon" - }, - "colorActive": { - "name": "$t:color-active-name", - "comment": "$t:color-active-comment", - "default": "pink-500", - "interface": "color-palette" - } - }, - "translation": { - "en-US": { - "toggle-icon": "Toggle Icon", - "text-inactive-name": "Text inactive", - "text-inactive-comment": "Text next to the inactive icon", - "text-inactive-placeholder": "Enter your text here", - "icon-inactive-name": "Inactive Icon", - "icon-inactive-comment": "Choose an inactive icon", - "color-inactive-name": "Inactive Color", - "color-inactive-comment": "Choose the inactive color", - "text-active-name": "Text active", - "text-active-comment": "Text next to the active icon", - "text-active-placeholder": "Enter your text here", - "icon-active-name": "active Icon", - "icon-active-comment": "Choose an active icon", - "color-active-name": "active Color", - "color-active-comment": "Choose the active color" - } - } -} diff --git a/extensions/core/interfaces/toggle/display.vue b/extensions/core/interfaces/toggle/display.vue deleted file mode 100644 index 2709ec18e3..0000000000 --- a/extensions/core/interfaces/toggle/display.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/toggle/input.vue b/extensions/core/interfaces/toggle/input.vue deleted file mode 100644 index 0a6924a1cc..0000000000 --- a/extensions/core/interfaces/toggle/input.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/toggle/meta.json b/extensions/core/interfaces/toggle/meta.json deleted file mode 100644 index e6cf7e7380..0000000000 --- a/extensions/core/interfaces/toggle/meta.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "$t:toggle", - "version": "1.0.0", - "types": ["boolean"], - "icon": "toggle_on", - "options": { - "labelOn": { - "name": "$t:label_on", - "comment": "$t:label_on_comment", - "interface": "text-input" - }, - "labelOff": { - "name": "$t:label_off", - "comment": "$t:label_off_comment", - "interface": "text-input" - }, - "checkbox": { - "name": "$t:checkbox", - "comment": "$t:checkbox_comment", - "interface": "toggle", - "default": false - } - }, - "translation": { - "en-US": { - "toggle": "Toggle", - "label_on": "Label (On)", - "label_on_comment": "Label to show next to the toggle when the toggle is on", - "label_off": "Label (Off)", - "label_off_comment": "Label to show next to the toggle when the toggle is off", - "checkbox": "Show as Checkbox", - "checkbox_comment": "Display a checkbox instead of the default switch" - } - } -} diff --git a/extensions/core/interfaces/translation/display.vue b/extensions/core/interfaces/translation/display.vue deleted file mode 100644 index 703be64100..0000000000 --- a/extensions/core/interfaces/translation/display.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/extensions/core/interfaces/translation/input.vue b/extensions/core/interfaces/translation/input.vue deleted file mode 100644 index 25082aacbb..0000000000 --- a/extensions/core/interfaces/translation/input.vue +++ /dev/null @@ -1,218 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/translation/meta.json b/extensions/core/interfaces/translation/meta.json deleted file mode 100644 index 7811931f16..0000000000 --- a/extensions/core/interfaces/translation/meta.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "$t:translation", - "version": "1.0.0", - "types": ["translation"], - "relation": "o2m", - "icon": "translate", - "options": { - "languagesCollection": { - "name": "$t:languages_collection", - "comment": "$t:languages_collection_comment", - "interface": "collections", - "required": true - }, - "languagesPrimaryKeyField": { - "name": "$t:languages_primary", - "comment": "$t:languages_primary_comment", - "interface": "text-input", - "required": true, - "options": { - "placeholder": "code" - } - }, - "languagesNameField": { - "name": "$t:languages_name", - "comment": "$t:languages_name_comment", - "interface": "text-input", - "required": true, - "options": { - "placeholder": "name" - } - }, - "translationLanguageField": { - "name": "$t:translation_language", - "comment": "$t:translation_language_comment", - "interface": "text-input", - "required": true, - "options": { - "placeholder": "language_code" - } - }, - "defaultLanguage": { - "name": "$t:default_language", - "comment": "$t:default_language_comment", - "interface": "text-input", - "required": true, - "options": { - "placeholder": "nl-NL" - } - } - }, - "translation": { - "en-US": { - "translation": "Translation", - "languages_collection": "Languages Collection", - "languages_collection_comment": "Collection that stores the language options", - "languages_primary": "Languages Primary Key Field", - "languages_primary_comment": "Field that holds the language primary key on the languages collection", - "languages_name": "Languages Name Field", - "languages_name_comment": "Field that holds the language's name on the languages collection", - "translation_language": "Translation Language Field", - "translation_language_comment": "The field that stores the language primary key in the related translations collection", - "translation_not_setup": "Interface not configured correctly", - "translation_no_languages": "There are no languages in the languages collection", - "default_language": "Default Language", - "default_language_comment": "Add the primary key of the item in the languages collection to use as the default language", - "choose_language": "Choose Language..." - } - } -} diff --git a/extensions/core/interfaces/user-created/display.vue b/extensions/core/interfaces/user-created/display.vue deleted file mode 100644 index 5b732caa43..0000000000 --- a/extensions/core/interfaces/user-created/display.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-created/input.vue b/extensions/core/interfaces/user-created/input.vue deleted file mode 100644 index dba1098c1d..0000000000 --- a/extensions/core/interfaces/user-created/input.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-created/meta.json b/extensions/core/interfaces/user-created/meta.json deleted file mode 100644 index 8d2012ab0d..0000000000 --- a/extensions/core/interfaces/user-created/meta.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "$t:user_created", - "version": "1.0.0", - "types": ["user_created"], - "icon": "account_circle", - "recommended": { - "length": 10 - }, - "options": { - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "default": "{{first_name}} {{last_name}}" - }, - "display": { - "name": "$t:display", - "comment": "$t:display_comment", - "interface": "dropdown", - "default": "both", - "options": { - "choices": { - "both": "$t:avatar + $t:name", - "avatar": "$t:avatar", - "name": "$t:name" - } - } - } - }, - "translation": { - "en-US": { - "user_created": "User Created", - "avatar": "Avatar", - "name": "Name", - "template": "Template", - "template_comment": "How to display the user on the item detail page", - "display": "Display", - "display_comment": "How to display the user on the item browse page", - "you": "You will be the creator", - "unknown": "Unknown" - } - } -} diff --git a/extensions/core/interfaces/user-roles/display.vue b/extensions/core/interfaces/user-roles/display.vue deleted file mode 100644 index ac0938442a..0000000000 --- a/extensions/core/interfaces/user-roles/display.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-roles/input.vue b/extensions/core/interfaces/user-roles/input.vue deleted file mode 100644 index 19331c25c2..0000000000 --- a/extensions/core/interfaces/user-roles/input.vue +++ /dev/null @@ -1,95 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-roles/meta.json b/extensions/core/interfaces/user-roles/meta.json deleted file mode 100644 index ab09223138..0000000000 --- a/extensions/core/interfaces/user-roles/meta.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "$t:user-roles", - "version": "1.0.0", - "types": ["o2m"], - "relation": "m2m", - "icon": "perm_identity", - "options": { - "relational": { - "name": "$t:relational", - "comment": "$t:relational_comment", - "interface": "toggle", - "default": true - } - }, - "translation": { - "en-US": { - "user-roles": "User Role", - "relational": "Relational", - "relational_comment": "Save as M2M value to directus_user_roles" - } - } -} diff --git a/extensions/core/interfaces/user-updated/display.vue b/extensions/core/interfaces/user-updated/display.vue deleted file mode 100644 index 5b732caa43..0000000000 --- a/extensions/core/interfaces/user-updated/display.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-updated/input.vue b/extensions/core/interfaces/user-updated/input.vue deleted file mode 100644 index c1799d6009..0000000000 --- a/extensions/core/interfaces/user-updated/input.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user-updated/meta.json b/extensions/core/interfaces/user-updated/meta.json deleted file mode 100644 index d0f80e5fac..0000000000 --- a/extensions/core/interfaces/user-updated/meta.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "$t:user_updated", - "version": "1.0.0", - "types": ["user_updated"], - "icon": "account_circle", - "recommended": { - "length": 10 - }, - "options": { - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "default": "{{first_name}} {{last_name}}" - }, - "display": { - "name": "$t:display", - "comment": "$t:display_comment", - "interface": "dropdown", - "default": "both", - "options": { - "choices": { - "both": "$t:avatar + $t:name", - "avatar": "$t:avatar", - "name": "$t:name" - } - } - } - }, - "translation": { - "en-US": { - "user_updated": "User Updated", - "avatar": "Avatar", - "name": "Name", - "template": "Template", - "template_comment": "How to display the user on the item detail page", - "display": "Display", - "display_comment": "How to display the user on the item browse page", - "you": "You will be the updater", - "unknown": "Unknown" - } - } -} diff --git a/extensions/core/interfaces/user/display.vue b/extensions/core/interfaces/user/display.vue deleted file mode 100644 index 5b732caa43..0000000000 --- a/extensions/core/interfaces/user/display.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user/input.vue b/extensions/core/interfaces/user/input.vue deleted file mode 100644 index 1fe3fdbd15..0000000000 --- a/extensions/core/interfaces/user/input.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/user/meta.json b/extensions/core/interfaces/user/meta.json deleted file mode 100644 index 102a5acbef..0000000000 --- a/extensions/core/interfaces/user/meta.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "$t:user", - "version": "1.0.1", - "types": ["integer", "user_created", "user_updated"], - "icon": "account_circle", - "recommended": { - "length": 10 - }, - "options": { - "template": { - "name": "$t:template", - "comment": "$t:template_comment", - "interface": "text-input", - "default": "{{first_name}} {{last_name}}" - }, - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "default": "Choose a User" - }, - "display": { - "name": "$t:display", - "comment": "$t:display_comment", - "interface": "dropdown", - "default": "both", - "options": { - "choices": { - "both": "$t:avatar + $t:name", - "avatar": "$t:avatar", - "name": "$t:name" - } - } - } - }, - "translation": { - "en-US": { - "user": "User", - "avatar": "Avatar", - "name": "Name", - "template": "Template", - "template_comment": "How to format the users in the dropdown", - "placeholder": "Placeholder", - "placeholder_comment": "Add a placeholder", - "display": "Display", - "display_comment": "How to display the users on the layouts" - } - } -} diff --git a/extensions/core/interfaces/wysiwyg-full/display.vue b/extensions/core/interfaces/wysiwyg-full/display.vue deleted file mode 100644 index 2258749c94..0000000000 --- a/extensions/core/interfaces/wysiwyg-full/display.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/extensions/core/interfaces/wysiwyg-full/input.vue b/extensions/core/interfaces/wysiwyg-full/input.vue deleted file mode 100644 index 401fb3d6f0..0000000000 --- a/extensions/core/interfaces/wysiwyg-full/input.vue +++ /dev/null @@ -1,199 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/wysiwyg-full/meta.json b/extensions/core/interfaces/wysiwyg-full/meta.json deleted file mode 100644 index dc42b45b71..0000000000 --- a/extensions/core/interfaces/wysiwyg-full/meta.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "name": "$t:wysiwyg_full", - "version": "1.0.1", - "types": ["string"], - "icon": "format_quote", - "recommended": { - "length": 65534 - }, - "options": { - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200 - }, - "upload_files": { - "name": "$t:upload_files", - "comment": "$t:upload_files_comment", - "interface": "toggle", - "type": "BOOLEAN", - "default": true - }, - "custom_url": { - "name": "$t:custom_url", - "comment": "$t:custom_url_comment", - "interface": "text-input", - "default": null, - "length": 250 - }, - "toolbarOptions": { - "name": "$t:toolbar_options", - "comment": "$t:toolbar_options_comment", - "interface": "code", - "options": { - "language": "application/json", - "template": [ - ["bold", "italic", "underline", "strike"], - ["blockquote", "code-block"], - ["image", "choose-existing"], - [{ "header": 1 }, { "header": 2 }], - [{ "list": "ordered"}, { "list": "bullet" }], - [{ "script": "sub"}, { "script": "super" }], - [{ "indent": "-1"}, { "indent": "+1" }], - [{ "direction": "rtl" }], - [{ "size": ["small", false, "large", "huge"] }], - [{ "header": [1, 2, 3, 4, 5, 6, false] }], - [{ "color": [] }, { "background": [] }], - [{ "font": [] }], - [{ "align": [] }], - ["clean"] - ] - }, - "default": [ - ["bold", "italic", "underline", "strike"], - ["blockquote", "code-block"], - ["image", "choose-existing"], - [{ "header": 1 }, { "header": 2 }], - [{ "list": "ordered"}, { "list": "bullet" }], - [{ "script": "sub"}, { "script": "super" }], - [{ "indent": "-1"}, { "indent": "+1" }], - [{ "header": [1, 2, 3, 4, 5, 6, false] }], - [{ "color": [] }, { "background": [] }], - [{ "align": [] }], - ["clean"] - ] - } - }, - "translation": { - "en-US": { - "wysiwyg_full": "Advanced WYSIWYG", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "toolbar_options": "Toolbar Options", - "toolbar_options_comment": "[QuillJS](https://quilljs.com/docs/modules/toolbar/) Toolbar options", - "upload_files": "Upload files", - "upload_files_comment": "Upload files to directus instead of using Base64 encoded images. Needs 'image' in toolbar.", - "custom_url": "URL base for images", - "custom_url_comment": "Optional custom URL base for images including last '/'" - } - } -} diff --git a/extensions/core/interfaces/wysiwyg-full/package.json b/extensions/core/interfaces/wysiwyg-full/package.json deleted file mode 100644 index 46c74b970a..0000000000 --- a/extensions/core/interfaces/wysiwyg-full/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "@directus/wysiwyg", - "version": "1.0.0", - "description": "", - "keywords": [], - "author": "", - "license": "GPL-3.0", - "dependencies": { - "quill": "^1.3.6", - "quill-image-upload": "^0.1.3" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/interfaces/wysiwyg-full/quill.theme.css b/extensions/core/interfaces/wysiwyg-full/quill.theme.css deleted file mode 100644 index 396033468b..0000000000 --- a/extensions/core/interfaces/wysiwyg-full/quill.theme.css +++ /dev/null @@ -1,604 +0,0 @@ -.ql-editor { - max-height: 600px; -} - -.ql-snow.ql-toolbar:after, -.ql-snow .ql-toolbar:after { - clear: both; - content: ''; - display: table; -} - -.ql-snow.ql-toolbar button, -.ql-snow .ql-toolbar button { - background: none; - border: none; - cursor: pointer; - display: inline-block; - float: left; - height: 24px; - padding: 3px 5px; - width: 28px; -} - -.ql-snow.ql-toolbar button svg, -.ql-snow .ql-toolbar button svg { - float: left; - height: 100%; -} - -.ql-snow.ql-toolbar button:active:hover, -.ql-snow .ql-toolbar button:active:hover { - outline: none; -} - -.ql-snow.ql-toolbar input.ql-image[type=file], -.ql-snow .ql-toolbar input.ql-image[type=file] { - display: none; -} - -.ql-snow.ql-toolbar button:hover, -.ql-snow .ql-toolbar button:hover, -.ql-snow.ql-toolbar button:focus, -.ql-snow .ql-toolbar button:focus, -.ql-snow.ql-toolbar button.ql-active, -.ql-snow .ql-toolbar button.ql-active, -.ql-snow.ql-toolbar .ql-picker-label:hover, -.ql-snow .ql-toolbar .ql-picker-label:hover, -.ql-snow.ql-toolbar .ql-picker-label.ql-active, -.ql-snow .ql-toolbar .ql-picker-label.ql-active, -.ql-snow.ql-toolbar .ql-picker-item:hover, -.ql-snow .ql-toolbar .ql-picker-item:hover, -.ql-snow.ql-toolbar .ql-picker-item.ql-selected, -.ql-snow .ql-toolbar .ql-picker-item.ql-selected { - color: var(--accent); -} - -.ql-snow.ql-toolbar button:hover .ql-fill, -.ql-snow .ql-toolbar button:hover .ql-fill, -.ql-snow.ql-toolbar button:focus .ql-fill, -.ql-snow .ql-toolbar button:focus .ql-fill, -.ql-snow.ql-toolbar button.ql-active .ql-fill, -.ql-snow .ql-toolbar button.ql-active .ql-fill, -.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill, -.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill, -.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill, -.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill, -.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill, -.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill, -.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill, -.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill, -.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill, -.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill, -.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill, -.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill, -.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill, -.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill, -.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, -.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, -.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, -.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, -.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, -.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, -.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill, -.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill { - fill: var(--accent); -} - -.ql-snow.ql-toolbar button:hover .ql-stroke, -.ql-snow .ql-toolbar button:hover .ql-stroke, -.ql-snow.ql-toolbar button:focus .ql-stroke, -.ql-snow .ql-toolbar button:focus .ql-stroke, -.ql-snow.ql-toolbar button.ql-active .ql-stroke, -.ql-snow .ql-toolbar button.ql-active .ql-stroke, -.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke, -.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke, -.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke, -.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke, -.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke, -.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke, -.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke, -.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke, -.ql-snow.ql-toolbar button:hover .ql-stroke-miter, -.ql-snow .ql-toolbar button:hover .ql-stroke-miter, -.ql-snow.ql-toolbar button:focus .ql-stroke-miter, -.ql-snow .ql-toolbar button:focus .ql-stroke-miter, -.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter, -.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter, -.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter, -.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter, -.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, -.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, -.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter, -.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter, -.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter, -.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter { - stroke: var(--accent); -} - -@media (pointer: coarse) { - .ql-snow.ql-toolbar button:hover:not(.ql-active), - .ql-snow .ql-toolbar button:hover:not(.ql-active) { - color: var(--light-gray); - } - .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill, - .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill, - .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill, - .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill { - fill: var(--light-gray); - } - .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke, - .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke, - .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter, - .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter { - stroke: var(--light-gray); - } -} - -.ql-snow { - box-sizing: border-box; -} -.ql-snow * { - box-sizing: border-box; -} -.ql-snow .ql-hidden { - display: none; -} -.ql-snow .ql-out-bottom, -.ql-snow .ql-out-top { - visibility: hidden; -} -.ql-snow .ql-tooltip { - position: absolute; - transform: translateY(10px); - z-index: 50; -} -.ql-snow .ql-tooltip a { - cursor: pointer; - text-decoration: none; -} -.ql-snow .ql-tooltip.ql-flip { - transform: translateY(-10px); -} -.ql-snow .ql-formats { - display: inline-block; - vertical-align: middle; -} -.ql-snow .ql-formats:after { - clear: both; - content: ''; - display: table; -} -.ql-snow .ql-stroke { - fill: none; - stroke: var(--light-gray); - stroke-linecap: round; - stroke-linejoin: round; - stroke-width: 2; -} -.ql-snow .ql-stroke-miter { - fill: none; - stroke: var(--light-gray); - stroke-miterlimit: 10; - stroke-width: 2; -} -.ql-snow .ql-fill, -.ql-snow .ql-stroke.ql-fill { - fill: var(--light-gray); -} -.ql-snow .ql-empty { - fill: none; -} -.ql-snow .ql-even { - fill-rule: evenodd; -} -.ql-snow .ql-thin, -.ql-snow .ql-stroke.ql-thin { - stroke-width: 1; -} -.ql-snow .ql-transparent { - opacity: 0.4; -} -.ql-snow .ql-direction svg:last-child { - display: none; -} -.ql-snow .ql-direction.ql-active svg:last-child { - display: inline; -} -.ql-snow .ql-direction.ql-active svg:first-child { - display: none; -} -.ql-snow .ql-editor h1 { - font-size: 2em; -} -.ql-snow .ql-editor h2 { - font-size: 1.5em; -} -.ql-snow .ql-editor h3 { - font-size: 1.17em; -} -.ql-snow .ql-editor h4 { - font-size: 1em; -} -.ql-snow .ql-editor h5 { - font-size: 0.83em; -} -.ql-snow .ql-editor h6 { - font-size: 0.67em; -} -.ql-snow .ql-editor a { - text-decoration: underline; -} -.ql-snow .ql-editor strong { - font-weight: 700; -} -.ql-snow .ql-editor em { - font-style: italic; -} -.ql-snow .ql-editor em { - font-style: italic; -} -.ql-snow .ql-editor blockquote { - border-left: 4px solid var(--lighter-gray); - margin-bottom: 5px; - margin-top: 5px; - padding-left: 16px; -} -.ql-snow .ql-editor code, -.ql-snow .ql-editor pre { - background-color: var(--lightest-gray); - border-radius: var(--border-radius); -} -.ql-snow .ql-editor pre { - white-space: pre-wrap; - margin-bottom: 5px; - margin-top: 5px; - padding: 15px 20px; -} -.ql-snow .ql-editor code { - font-family: monospace; - padding: 2px 4px; -} -.ql-snow .ql-editor pre.ql-syntax { - background-color: var(--darkest-gray); - color: var(--lightest-gray); - overflow: visible; -} -.ql-snow .ql-editor img { - max-width: 100%; -} -.ql-snow .ql-editor { - transition: color var(--fast) var(--transition); - min-height: 200px; - line-height: 1.8; - word-break: break-word; - overflow-wrap: break-word; - word-wrap: break-word; -} -.ql-snow .ql-picker { - color: var(--gray); - display: inline-block; - float: left; - font-size: 14px; - font-weight: 500; - height: 24px; - position: relative; - vertical-align: middle; -} -.ql-snow .ql-picker-label { - cursor: pointer; - display: inline-block; - height: 100%; - padding-left: 8px; - padding-right: 2px; - position: relative; - width: 100%; -} -.ql-snow .ql-picker-label::before { - display: inline-block; - line-height: 22px; -} -.ql-snow .ql-picker-options { - background-color: #fff; - display: none; - min-width: 100%; - padding: 4px 8px; - position: absolute; - white-space: nowrap; -} -.ql-snow .ql-picker-options .ql-picker-item { - cursor: pointer; - display: block; - padding-bottom: 5px; - padding-top: 5px; -} -.ql-snow .ql-picker.ql-expanded .ql-picker-label { - color: #ccc; - z-index: 2; -} -.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill { - fill: #ccc; -} -.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke { - stroke: #ccc; -} -.ql-snow .ql-picker.ql-expanded .ql-picker-options { - display: block; - margin-top: -1px; - top: 100%; - z-index: 1; -} -.ql-snow .ql-color-picker, -.ql-snow .ql-icon-picker { - width: 28px; -} -.ql-snow .ql-color-picker .ql-picker-label, -.ql-snow .ql-icon-picker .ql-picker-label { - padding: 2px 4px; -} -.ql-snow .ql-color-picker .ql-picker-label svg, -.ql-snow .ql-icon-picker .ql-picker-label svg { - right: 4px; -} -.ql-snow .ql-icon-picker .ql-picker-options { - padding: 4px 0px; -} -.ql-snow .ql-icon-picker .ql-picker-item { - height: 24px; - width: 24px; - padding: 2px 4px; -} -.ql-snow .ql-color-picker .ql-picker-options { - padding: 3px 5px; - width: 152px; -} -.ql-snow .ql-color-picker .ql-picker-item { - border: 1px solid transparent; - float: left; - height: 16px; - margin: 2px; - padding: 0px; - width: 16px; -} -.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg { - position: absolute; - margin-top: -9px; - right: 0; - top: 50%; - width: 18px; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before, -.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before, -.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before, -.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before, -.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before { - content: attr(data-label); -} -.ql-snow .ql-picker.ql-header { - width: 98px; -} -.ql-snow .ql-picker.ql-header .ql-picker-label::before, -.ql-snow .ql-picker.ql-header .ql-picker-item::before { - content: 'Normal'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { - content: 'Heading 1'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { - content: 'Heading 2'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { - content: 'Heading 3'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { - content: 'Heading 4'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { - content: 'Heading 5'; -} -.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { - content: 'Heading 6'; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { - font-size: 2em; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { - font-size: 1.5em; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { - font-size: 1.17em; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { - font-size: 1em; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { - font-size: 0.83em; -} -.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { - font-size: 0.67em; -} -.ql-snow .ql-picker.ql-font { - width: 108px; -} -.ql-snow .ql-picker.ql-font .ql-picker-label::before, -.ql-snow .ql-picker.ql-font .ql-picker-item::before { - content: 'Sans Serif'; -} -.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before, -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { - content: 'Serif'; -} -.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before, -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { - content: 'Monospace'; -} -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { - font-family: Georgia, Times New Roman, serif; -} -.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { - font-family: Monaco, Courier New, monospace; -} -.ql-snow .ql-picker.ql-size { - width: 98px; -} -.ql-snow .ql-picker.ql-size .ql-picker-label::before, -.ql-snow .ql-picker.ql-size .ql-picker-item::before { - content: 'Normal'; -} -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { - content: 'Small'; -} -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { - content: 'Large'; -} -.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { - content: 'Huge'; -} -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { - font-size: 10px; -} -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { - font-size: 18px; -} -.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { - font-size: 32px; -} -.ql-snow .ql-color-picker.ql-background .ql-picker-item { - background-color: #fff; -} -.ql-snow .ql-color-picker.ql-color .ql-picker-item { - background-color: #000; -} -.ql-toolbar.ql-snow { - box-sizing: border-box; - font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; - padding: 8px; - border-radius: var(--border-radius) var(--border-radius) 0 0; - border: var(--input-border-width) solid var(--lighter-gray); -} -.ql-toolbar.ql-snow .ql-formats { - margin-right: 15px; -} -.ql-toolbar.ql-snow .ql-picker-label { - border: 1px solid transparent; -} -.ql-toolbar.ql-snow .ql-picker-options { - border: 1px solid transparent; - box-shadow: rgba(0,0,0,0.2) 0 2px 8px; -} -.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label { - border-color: #ccc; -} -.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { - border-color: #ccc; -} -.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected, -.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover { - border-color: #000; -} -.ql-toolbar.ql-snow { - border-bottom: 0px; -} -.ql-toolbar.ql-snow + .ql-container.ql-snow { - border-radius: 0 0 var(--border-radius) var(--border-radius); -} -.ql-snow .ql-tooltip { - background-color: var(--white); - box-shadow: var(--box-shadow); - color: var(--gray); - padding: 20px; - white-space: nowrap; - border-radius: var(--border-radius); - border: var(--input-border-width) solid var(--lighter-gray); -} -.ql-snow .ql-tooltip::before { - content: "Visit URL:"; - line-height: 26px; - margin-right: 8px; -} -.ql-snow .ql-tooltip input[type=text] { - display: none; - border-radius: var(--border-radius); - border: var(--input-border-width) solid var(--lighter-gray); - font-size: 13px; - height: 26px; - margin: 0px; - padding: 3px 5px; - width: 170px; -} -.ql-snow .ql-tooltip a.ql-preview { - display: inline-block; - max-width: 200px; - overflow-x: hidden; - text-overflow: ellipsis; - vertical-align: top; -} -.ql-snow .ql-tooltip a.ql-action::after { - border-right: 1px solid #ccc; - content: 'Edit'; - margin-left: 16px; - padding-right: 8px; -} -.ql-snow .ql-tooltip a.ql-remove::before { - content: 'Remove'; - margin-left: 8px; -} -.ql-snow .ql-tooltip a { - line-height: 26px; -} -.ql-snow .ql-tooltip.ql-editing a.ql-preview, -.ql-snow .ql-tooltip.ql-editing a.ql-remove { - display: none; -} -.ql-snow .ql-tooltip.ql-editing input[type=text] { - display: inline-block; -} -.ql-snow .ql-tooltip.ql-editing a.ql-action::after { - border-right: 0px; - content: 'Save'; - padding-right: 0px; -} -.ql-snow .ql-tooltip[data-mode=link]::before { - content: "Link:"; -} -.ql-snow .ql-tooltip[data-mode=formula]::before { - content: "Formula:"; -} -.ql-snow .ql-tooltip[data-mode=video]::before { - content: "Video:"; -} -.ql-snow a { - color: var(--accent); -} -.ql-container.ql-snow { - transition: border-color var(--fast) var(--transition); - background-color: var(--white); - border-radius: var(--border-radius); - border: var(--input-border-width) solid var(--lighter-gray); - - -webkit-font-smoothing: antialiased; - text-rendering: optimizeLegibility; - -moz-osx-font-smoothing: grayscale; - font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-weight: 400; - line-height: 1.8; - color: var(--gray); -} - -.ql-container.ql-snow:hover { - border-color: var(--light-gray); -} - -.ql-container.ql-snow:focus-within { - border-color: var(--accent); -} diff --git a/extensions/core/interfaces/wysiwyg/display.vue b/extensions/core/interfaces/wysiwyg/display.vue deleted file mode 100644 index 1a9908c751..0000000000 --- a/extensions/core/interfaces/wysiwyg/display.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/extensions/core/interfaces/wysiwyg/input.vue b/extensions/core/interfaces/wysiwyg/input.vue deleted file mode 100644 index ee4628b37f..0000000000 --- a/extensions/core/interfaces/wysiwyg/input.vue +++ /dev/null @@ -1,421 +0,0 @@ - - - - - diff --git a/extensions/core/interfaces/wysiwyg/meta.json b/extensions/core/interfaces/wysiwyg/meta.json deleted file mode 100644 index 2bedbb8d70..0000000000 --- a/extensions/core/interfaces/wysiwyg/meta.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "$t:wysiwyg", - "version": "1.0.1", - "types": ["string"], - "icon": "format_quote", - "recommended": { - "length": 65534 - }, - "options": { - "placeholder": { - "name": "$t:placeholder", - "comment": "$t:placeholder_comment", - "interface": "text-input", - "length": 200 - }, - "buttons": { - "name": "$t:buttons", - "comment": "$t:buttons_comment", - "interface": "checkboxes", - "default": ["bold", "italic", "underline", "anchor", "h2", "h3", "quote"], - "options": { - "wrap": false, - "choices": { - "bold": "Bold", - "italic": "Italic", - "underline": "Underline", - "strikethrough": "Strikethrough", - "subscript": "Subscript", - "superscript": "Superscript", - "anchor": "Link", - "quote": "Quote", - "pre": "Pre", - "orderedlist": "Ordered List", - "unorderedlist": "Unordered List", - "h1": "H1", - "h2": "H2", - "h3": "H3", - "h4": "H4", - "h5": "H5", - "h6": "H6", - "removeFormat": "Remove all formatting" - } - } - } - }, - "translation": { - "en-US": { - "wysiwyg": "WYSIWYG", - "placeholder": "Placeholder", - "placeholder_comment": "Enter placeholder text", - "buttons": "Buttons", - "buttons_comment": "Choose what buttons to use in the toolbar", - "distraction_free_mode": "Distracton Free Mode" - } - } -} diff --git a/extensions/core/interfaces/wysiwyg/package.json b/extensions/core/interfaces/wysiwyg/package.json deleted file mode 100644 index 6506ed632a..0000000000 --- a/extensions/core/interfaces/wysiwyg/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "@directus/wysiwyg", - "version": "1.0.0", - "description": "", - "keywords": [], - "author": "", - "license": "GPL-3.0", - "dependencies": { - "medium-editor": "^5.23.3" - }, - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/core/layouts/calendar/Calendar.vue b/extensions/core/layouts/calendar/Calendar.vue deleted file mode 100644 index 5db9451900..0000000000 --- a/extensions/core/layouts/calendar/Calendar.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/calendar/Day.vue b/extensions/core/layouts/calendar/Day.vue deleted file mode 100644 index 4e048b3cf4..0000000000 --- a/extensions/core/layouts/calendar/Day.vue +++ /dev/null @@ -1,146 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/calendar/Popup.vue b/extensions/core/layouts/calendar/Popup.vue deleted file mode 100644 index c55b011d42..0000000000 --- a/extensions/core/layouts/calendar/Popup.vue +++ /dev/null @@ -1,414 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/calendar/layout.vue b/extensions/core/layouts/calendar/layout.vue deleted file mode 100644 index 0eb7ac5f73..0000000000 --- a/extensions/core/layouts/calendar/layout.vue +++ /dev/null @@ -1,401 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/calendar/meta.json b/extensions/core/layouts/calendar/meta.json deleted file mode 100644 index b72f8014a4..0000000000 --- a/extensions/core/layouts/calendar/meta.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "$t:calendar", - "version": "1.0.0", - "translation": { - "en-US": { - "calendar": "Calendar", - "fields": "Fields", - "today": "today", - "events": "Events", - "moreEvents": "and {amount} more...", - "noEvents": "no events yet!", - "date": "Date", - "time": "Time", - "title": "Title", - "color": "Color", - "months": { - "january": "January", - "february": "February", - "march": "March", - "april": "April", - "may": "May", - "june": "June", - "july": "July", - "august": "August", - "september": "September", - "october": "October", - "november": "November", - "december": "December" - }, - "weeks": { - "monday": "Monday", - "tuesday": "Tuesday", - "wednesday": "Wednesday", - "thursday": "Thursday", - "friday": "Friday", - "saturday": "Saturday", - "sunday": "Sunday" - } - }, - "de-DE": { - "calendar": "Kalendar", - "today": "Heute", - "events": "Termine", - "moreEvents": "und {amount} mehr...", - "noEvents": "noch keine Termine!", - "date": "Datum", - "time": "Zeit", - "title": "Titel", - "color": "Farbe", - "months": { - "january": "Januar", - "february": "Februar", - "march": "März", - "april": "April", - "may": "Mai", - "june": "Juni", - "july": "Juli", - "august": "August", - "september": "September", - "october": "Oktober", - "november": "November", - "december": "Dezember" - }, - "weeks": { - "monday": "Montag", - "tuesday": "Dienstag", - "wednesday": "Mittwoch", - "thursday": "Donnerstag", - "friday": "Freitag", - "saturday": "Samstag", - "sunday": "Sonntag" - } - } - } -} diff --git a/extensions/core/layouts/calendar/options.vue b/extensions/core/layouts/calendar/options.vue deleted file mode 100644 index 189dc50b0f..0000000000 --- a/extensions/core/layouts/calendar/options.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/cards/layout.vue b/extensions/core/layouts/cards/layout.vue deleted file mode 100644 index 59ed795cac..0000000000 --- a/extensions/core/layouts/cards/layout.vue +++ /dev/null @@ -1,239 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/cards/meta.json b/extensions/core/layouts/cards/meta.json deleted file mode 100644 index b59bcd6d3f..0000000000 --- a/extensions/core/layouts/cards/meta.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "$t:cards", - "version": "1.0.1", - "translation": { - "en-US": { - "cards": "Cards", - "title": "Title", - "subtitle": "Subtitle", - "src": "Image Source", - "content": "Body Content" - } - } -} diff --git a/extensions/core/layouts/cards/options.vue b/extensions/core/layouts/cards/options.vue deleted file mode 100644 index 14055b9ba3..0000000000 --- a/extensions/core/layouts/cards/options.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - - diff --git a/extensions/core/layouts/tabular/layout.vue b/extensions/core/layouts/tabular/layout.vue deleted file mode 100644 index 063a4915e3..0000000000 --- a/extensions/core/layouts/tabular/layout.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - diff --git a/extensions/core/layouts/tabular/meta.json b/extensions/core/layouts/tabular/meta.json deleted file mode 100644 index f57d01c6ed..0000000000 --- a/extensions/core/layouts/tabular/meta.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "$t:tabular", - "version": "1.0.0", - "translation": { - "en-US": { - "tabular": "Table", - "fields": "Fields" - }, - "nl-NL": { - "tabular": "Tabel", - "fields": "Kolommen" - } - } -} diff --git a/extensions/core/layouts/tabular/options.vue b/extensions/core/layouts/tabular/options.vue deleted file mode 100644 index 94b0e53a4c..0000000000 --- a/extensions/core/layouts/tabular/options.vue +++ /dev/null @@ -1,138 +0,0 @@ - - - - - diff --git a/extensions/core/pages/_demo/meta.json b/extensions/core/pages/_demo/meta.json deleted file mode 100644 index 92ba759d7a..0000000000 --- a/extensions/core/pages/_demo/meta.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Demo Page", - "version": "1.0.0", - "icon": "person", - "translation": {} -} diff --git a/extensions/core/pages/_demo/page.vue b/extensions/core/pages/_demo/page.vue deleted file mode 100644 index 99183a812e..0000000000 --- a/extensions/core/pages/_demo/page.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/extensions/json-minifier.js b/extensions/json-minifier.js deleted file mode 100644 index 7eb7bbea4e..0000000000 --- a/extensions/json-minifier.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * This transformation is used in the copy command for the meta.json files - * - * It takes the contents of the json file, minifies it, and returns it. - */ - -var through = require("through2"); -var jsonminify = require("jsonminify"); - -module.exports = function(file) { - return through(function(buf, enc, next) { - this.push(jsonminify(buf.toString("utf8"))); - next(); - }); -}; diff --git a/extensions/mixins/interface.js b/extensions/mixins/interface.js deleted file mode 100644 index 8c0bf8c976..0000000000 --- a/extensions/mixins/interface.js +++ /dev/null @@ -1,48 +0,0 @@ -module.exports = { - props: { - name: { - type: String, - required: true - }, - value: { - type: null, - default: null - }, - type: { - type: String, - required: true - }, - length: { - type: [String, Number], - default: null - }, - readonly: { - type: Boolean, - default: false - }, - required: { - type: Boolean, - default: false - }, - options: { - type: Object, - default: () => ({}) - }, - newItem: { - type: Boolean, - default: false - }, - relation: { - type: Object, - default: null - }, - fields: { - type: Object, - default: null - }, - values: { - type: Object, - default: null - } - } -}; diff --git a/extensions/mixins/layout.js b/extensions/mixins/layout.js deleted file mode 100644 index 7e77cd0b8f..0000000000 --- a/extensions/mixins/layout.js +++ /dev/null @@ -1,44 +0,0 @@ -module.exports = { - props: { - primaryKeyField: { - type: String, - required: true - }, - fields: { - type: Object, - required: true - }, - items: { - type: Array, - default: () => ([]) - }, - viewOptions: { - type: Object, - default: () => ({}) - }, - viewQuery: { - type: Object, - default: () => ({}) - }, - loading: { - type: Boolean, - default: false - }, - lazyLoading: { - type: Boolean, - default: false - }, - selection: { - type: Array, - default: () => [] - }, - link: { - type: String, - default: null - }, - sortField: { - type: String, - default: null - } - } -}; diff --git a/extensions/mixins/package.json b/extensions/mixins/package.json deleted file mode 100644 index d716ac1558..0000000000 --- a/extensions/mixins/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@directus/mixins", - "version": "1.1.0", - "description": "", - "main": "interface.js", - "keywords": [ - "directus", - "extensions", - "mixin", - "vue" - ], - "author": "Rijk van Zanten ", - "license": "GPL-3.0", - "devDependencies": { - "babel-core": "^6.26.3" - } -} diff --git a/extensions/mixins/page.js b/extensions/mixins/page.js deleted file mode 100644 index f4d625303f..0000000000 --- a/extensions/mixins/page.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - -}; diff --git a/extensions/package.json b/extensions/package.json deleted file mode 100644 index 823e86834a..0000000000 --- a/extensions/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "@directus/extensions-builder", - "version": "1.0.0", - "description": "", - "scripts": { - "postinstall": "npx recursive-install --skip-root", - "prebuild": "npm run clear", - "clear": "rimraf ../public/extensions/core/{interfaces,layouts,pages}", - "dev:json": "cpx \"core/**/meta.json\" ../public/extensions/core -w", - "dev:php": "cpx \"core/**/{hooks.php,endpoints.php}\" ../public/extensions/core", - "dev:vue": "parcel watch core/**/*.vue -d ../public/extensions/core --no-source-maps --global __DirectusExtension__", - "build:php": "cpx \"core/**/{hooks.php,endpoints.php}\" ../public/extensions/core", - "build:json": "cpx \"core/**/meta.json\" ../public/extensions/core -t ./json-minifier.js -v", - "build:vue": "parcel build \"core/**/*.vue\" -d ../public/extensions/core --no-source-maps --global __DirectusExtension__", - "build": "npm run build:vue && npm run build:json && npm run build:php", - "dev": "npm run build:json && concurrently --raw \"npm run dev:vue\" \"npm run dev:json\" \"npm run dev:php\"", - "lint": "vue-cli-service lint \"core/**/*.vue\"", - "fix": "prettier --write \"core/**/*.{js,vue}\"" - }, - "author": "Rijk van Zanten ", - "license": "GPL-3.0", - "devDependencies": { - "@vue/cli-plugin-babel": "^3.0.0-rc.3", - "@vue/cli-plugin-eslint": "^3.0.0-rc.3", - "@vue/cli-service": "^3.0.0-rc.3", - "@vue/component-compiler-utils": "^2.0.0", - "@vue/eslint-config-prettier": "^3.0.0-rc.3", - "babel-core": "^6.26.3", - "babel-preset-env": "^1.7.0", - "babel-preset-stage-2": "^6.24.1", - "concurrently": "^3.6.0", - "cpx": "^1.5.0", - "jsonminify": "^0.4.1", - "node-sass": "^4.9.4", - "parcel-bundler": "^1.10.3", - "prettier": "^1.15.2", - "recursive-install": "^1.3.0", - "rimraf": "^2.6.2", - "through2": "^2.0.3", - "vue-template-compiler": "^2.5.16" - }, - "dependencies": { - "vue": "^2.5.16", - "vue-hot-reload-api": "^2.3.0" - }, - "eslintConfig": { - "root": true, - "extends": [ - "plugin:vue/essential", - "@vue/prettier" - ], - "parser": "vue-eslint-parser", - "parserOptions": { - "parser": "babel-eslint", - "ecmaVersion": 8, - "sourceType": "module" - } - } -} diff --git a/migrations/db/schemas/20180220023138_create_activity_table.php b/migrations/db/schemas/20180220023138_create_activity_table.php index c10e50a41c..ae602ee604 100644 --- a/migrations/db/schemas/20180220023138_create_activity_table.php +++ b/migrations/db/schemas/20180220023138_create_activity_table.php @@ -68,7 +68,8 @@ public function change() ]); $table->addColumn('comment', 'text', [ - 'null' => true + 'null' => true, + 'encoding' => 'utf8mb4' ]); $table->addColumn('comment_deleted_on', 'datetime', [ diff --git a/migrations/db/schemas/20180220023152_create_collections_presets_table.php b/migrations/db/schemas/20180220023152_create_collections_presets_table.php index f3c9171553..f4f38af82e 100644 --- a/migrations/db/schemas/20180220023152_create_collections_presets_table.php +++ b/migrations/db/schemas/20180220023152_create_collections_presets_table.php @@ -32,7 +32,8 @@ public function change() $table->addColumn('title', 'string', [ 'limit' => 255, 'null' => true, - 'default' => null + 'default' => null, + 'encoding' => 'utf8mb4' ]); $table->addColumn('user', 'integer', [ 'signed' => false, diff --git a/migrations/db/schemas/20180220023202_create_fields_table.php b/migrations/db/schemas/20180220023202_create_fields_table.php index 99194932c6..275ecbd6a2 100644 --- a/migrations/db/schemas/20180220023202_create_fields_table.php +++ b/migrations/db/schemas/20180220023202_create_fields_table.php @@ -85,10 +85,10 @@ public function change() 'null' => true, 'default' => null ]); - $table->addColumn('width', 'integer', [ - 'signed' => false, - 'null' => false, - 'default' => 4 + $table->addColumn('width', 'string', [ + 'limit' => 50, + 'null' => true, + 'default' => 'full' ]); $table->addColumn('group', 'integer', [ 'signed' => false, diff --git a/migrations/db/seeds/FieldsSeeder.php b/migrations/db/seeds/FieldsSeeder.php index 14c559afde..57bbf90945 100644 --- a/migrations/db/seeds/FieldsSeeder.php +++ b/migrations/db/seeds/FieldsSeeder.php @@ -45,7 +45,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 2, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -55,7 +55,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 3, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -65,7 +65,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 4, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -78,7 +78,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 5, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -91,7 +91,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 6, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -104,7 +104,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 7, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -114,7 +114,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 8, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -124,7 +124,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 9, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_activity', @@ -185,14 +185,14 @@ public function run() 'collection' => 'directus_collection_presets', 'field' => 'filters', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ 'collection' => 'directus_collection_presets', 'field' => 'view_options', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ @@ -206,7 +206,7 @@ public function run() 'collection' => 'directus_collection_presets', 'field' => 'view_query', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], @@ -231,7 +231,7 @@ public function run() 'readonly' => true, 'required' => true, 'sort' => 2, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_collections', @@ -240,7 +240,8 @@ public function run() 'interface' => 'text-input', 'locked' => true, 'sort' => 3, - 'width' => 2 + 'width' => 'half', + 'note' => 'An internal description.' ], [ 'collection' => 'directus_collections', @@ -249,7 +250,9 @@ public function run() 'interface' => 'toggle', 'locked' => true, 'sort' => 4, - 'width' => 1 + 'width' => 'half', + 'hidden_detail' => true, + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#managing-collections).' ], [ 'collection' => 'directus_collections', @@ -258,7 +261,8 @@ public function run() 'interface' => 'toggle', 'locked' => true, 'sort' => 5, - 'width' => 1 + 'width' => 'half', + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#hidden).' ], [ 'collection' => 'directus_collections', @@ -267,13 +271,14 @@ public function run() 'interface' => 'toggle', 'locked' => true, 'sort' => 6, - 'width' => 1 + 'width' => 'half', + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#single).' ], [ 'collection' => 'directus_collections', 'field' => 'translation', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true, 'sort' => 7, 'hidden_detail' => true @@ -284,7 +289,8 @@ public function run() 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, 'interface' => 'icon', 'locked' => true, - 'sort' => 8 + 'sort' => 8, + 'note' => 'The icon shown in the App\'s navigation sidebar.' ], @@ -331,7 +337,7 @@ public function run() 'collection' => 'directus_fields', 'field' => 'options', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ @@ -345,7 +351,7 @@ public function run() 'collection' => 'directus_fields', 'field' => 'translation', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ @@ -453,7 +459,7 @@ public function run() ]), 'locked' => true, 'sort' => 3, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -467,7 +473,8 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 4, - 'width' => 2 + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_files', @@ -475,7 +482,7 @@ public function run() 'type' => \Directus\Database\Schema\DataTypes::TYPE_ARRAY, 'interface' => 'tags', 'sort' => 5, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -487,7 +494,7 @@ public function run() 'iconRight' => 'place' ]), 'sort' => 6, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -509,8 +516,8 @@ public function run() ]), 'locked' => true, 'readonly' => true, - 'sort' => 8, - 'width' => 1 + 'sort' => 10, + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -522,8 +529,8 @@ public function run() ]), 'locked' => true, 'readonly' => true, - 'sort' => 9, - 'width' => 1 + 'sort' => 11, + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -535,8 +542,8 @@ public function run() ]), 'locked' => true, 'readonly' => true, - 'sort' => 10, - 'width' => 1 + 'sort' => 12, + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -548,8 +555,8 @@ public function run() ]), 'locked' => true, 'readonly' => true, - 'sort' => 11, - 'width' => 1 + 'sort' => 13, + 'width' => 'half' ], [ 'collection' => 'directus_files', @@ -561,8 +568,9 @@ public function run() ]), 'locked' => true, 'readonly' => true, - 'sort' => 12, - 'width' => 2 + 'sort' => 8, + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_files', @@ -571,17 +579,17 @@ public function run() 'interface' => 'user', 'locked' => true, 'readonly' => true, - 'sort' => 13, - 'width' => 2 + 'sort' => 9, + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_files', 'field' => 'metadata', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true, - 'sort' => 14, - 'width' => 4 + 'sort' => 14 ], [ 'collection' => 'directus_files', @@ -636,6 +644,7 @@ public function run() 'locked' => true, 'readonly' => true, 'hidden_detail' => true, + 'hidden_browse' => true ], @@ -843,14 +852,14 @@ public function run() 'collection' => 'directus_revisions', 'field' => 'data', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ 'collection' => 'directus_revisions', 'field' => 'delta', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true ], [ @@ -904,7 +913,8 @@ public function run() 'interface' => 'text-input', 'locked' => true, 'sort' => 1, - 'width' => 2 + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_roles', @@ -913,7 +923,7 @@ public function run() 'interface' => 'text-input', 'locked' => true, 'sort' => 2, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_roles', @@ -936,49 +946,17 @@ public function run() 'field' => 'users', 'type' => \Directus\Database\Schema\DataTypes::TYPE_O2M, 'interface' => 'many-to-many', - 'locked' => true - ], - [ - 'collection' => 'directus_roles', - 'field' => 'nav_override', - 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', - 'locked' => 1, - 'options' => '[ - { - "title": "$t:collections", - "include": "collections" - }, - { - "title": "$t:bookmarks", - "include": "bookmarks" - }, - { - "title": "$t:extensions", - "include": "extensions" - }, - { - "title": "Custom Links", - "links": [ - { - "name": "RANGER Studio", - "path": "https://rangerstudio.com", - "icon": "star" - }, - { - "name": "Movies", - "path": "/collections/movies" - } - ] - } - ]' + 'locked' => true, + 'options' => json_encode([ + 'fields' => "first_name,last_name" + ]) ], [ 'collection' => 'directus_roles', 'field' => 'nav_override', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', - 'locked' => 1, + 'interface' => 'json', + 'locked' => true, 'options' => '[ { "title": "$t:collections", @@ -1016,42 +994,52 @@ public function run() 'field' => 'project_name', 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, 'interface' => 'text-input', - 'locked' => true - ], - [ - 'collection' => 'directus_settings', - 'field' => 'project_url', - 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, - 'interface' => 'text-input', - 'locked' => true + 'locked' => true, + 'required' => true, + 'width' => 'half-space', + 'sort' => 1 ], [ 'collection' => 'directus_settings', - 'field' => 'app_url', + 'field' => 'color', 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, - 'interface' => 'text-input', - 'locked' => true + 'interface' => 'color-palette', + 'locked' => true, + 'width' => 'half', + 'note' => 'The color that best fits your brand.', + 'sort' => 2 ], [ 'collection' => 'directus_settings', 'field' => 'logo', 'type' => \Directus\Database\Schema\DataTypes::TYPE_FILE, 'interface' => 'file', - 'locked' => true + 'locked' => true, + 'width' => 'half', + 'note' => 'Your brand\'s logo.', + 'sort' => 3 ], [ 'collection' => 'directus_settings', - 'field' => 'color', + 'field' => 'app_url', 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, - 'interface' => 'color-palette', - 'locked' => true + 'interface' => 'text-input', + 'locked' => true, + 'required' => true, + 'width' => 'half-space', + 'note' => 'The URL where your app is hosted. The API will use this to direct your users to the correct login page.', + 'sort' => 4 ], [ 'collection' => 'directus_settings', 'field' => 'default_limit', 'type' => \Directus\Database\Schema\DataTypes::TYPE_INTEGER, 'interface' => 'numeric', - 'locked' => true + 'locked' => true, + 'required' => true, + 'width' => 'half', + 'note' => 'Default max amount of items that\'s returned at a time in the API.', + 'sort' => 5 ], [ 'collection' => 'directus_settings', @@ -1059,63 +1047,81 @@ public function run() 'type' => \Directus\Database\Schema\DataTypes::TYPE_BOOLEAN, 'interface' => 'toggle', 'locked' => true, - 'note' => 'Will sort values with null at the end of the result' + 'note' => 'Will sort values with null at the end of the result', + 'width' => 'half', + 'note' => 'Put items with `null` for the value last when sorting.', + 'sort' => 6 ], [ 'collection' => 'directus_settings', 'field' => 'auto_sign_out', 'type' => \Directus\Database\Schema\DataTypes::TYPE_INTEGER, 'interface' => 'numeric', - 'locked' => true - ], - [ - 'collection' => 'directus_settings', - 'field' => 'trusted_proxies', - 'type' => \Directus\Database\Schema\DataTypes::TYPE_ARRAY, - 'interface' => 'tags', - 'locked' => true + 'locked' => true, + 'required' => true, + 'width' => 'half', + 'note' => 'How many minutes before an idle user is signed out.', + 'sort' => 7 ], [ 'collection' => 'directus_settings', 'field' => 'youtube_api', 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, 'interface' => 'text-input', - 'locked' => true + 'locked' => true, + 'width' => 'half', + 'note' => 'When provided, this allows more information to be collected for YouTube embeds.', + 'sort' => 8 ], [ 'collection' => 'directus_settings', 'field' => 'thumbnail_dimensions', 'type' => \Directus\Database\Schema\DataTypes::TYPE_ARRAY, 'interface' => 'tags', - 'locked' => true + 'locked' => true, + 'note' => 'Allowed dimensions for thumbnails.', + 'sort' => 9 ], [ 'collection' => 'directus_settings', 'field' => 'thumbnail_quality_tags', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', - 'locked' => true + 'interface' => 'json', + 'locked' => true, + 'width' => 'half', + 'note' => 'Allowed quality for thumbnails.', + 'sort' => 10 ], [ 'collection' => 'directus_settings', 'field' => 'thumbnail_actions', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', - 'locked' => true + 'interface' => 'json', + 'locked' => true, + 'width' => 'half', + 'note' => 'Defines how the thumbnail will be generated based on the requested dimensions.', + 'sort' => 11 ], [ 'collection' => 'directus_settings', 'field' => 'thumbnail_cache_ttl', 'type' => \Directus\Database\Schema\DataTypes::TYPE_INTEGER, 'interface' => 'numeric', - 'locked' => true + 'locked' => true, + 'width' => 'half', + 'required' => true, + 'note' => '`max-age` HTTP header of the thumbnail.', + 'sort' => 12 ], [ 'collection' => 'directus_settings', 'field' => 'thumbnail_not_found_location', 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, 'interface' => 'text-input', - 'locked' => true + 'locked' => true, + 'width' => 'half', + 'note' => 'This image will be used when trying to generate a thumbnail with invalid options or an error happens on the server when creating the image.', + 'sort' => 13 ], @@ -1182,6 +1188,7 @@ public function run() ]), 'locked' => true, 'sort' => 2, + 'required' => true ], [ 'collection' => 'directus_users', @@ -1194,7 +1201,7 @@ public function run() 'locked' => true, 'required' => true, 'sort' => 3, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1207,7 +1214,7 @@ public function run() 'locked' => true, 'required' => true, 'sort' => 4, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1221,7 +1228,7 @@ public function run() 'validation' => '$email', 'required' => true, 'sort' => 5, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1230,17 +1237,17 @@ public function run() 'interface' => 'toggle', 'locked' => true, 'sort' => 6, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', 'field' => 'password', - 'type' => \Directus\Database\Schema\DataTypes::TYPE_STRING, + 'type' => \Directus\Database\Schema\DataTypes::TYPE_HASH, 'interface' => 'password', 'locked' => true, 'required' => true, 'sort' => 7, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1249,7 +1256,8 @@ public function run() 'interface' => 'user-roles', 'locked' => true, 'sort' => 8, - 'width' => 2 + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_users', @@ -1260,7 +1268,7 @@ public function run() 'placeholder' => 'Enter your company or organization name...' ]), 'sort' => 9, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1271,7 +1279,7 @@ public function run() 'placeholder' => 'Enter your title or role...' ]), 'sort' => 10, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1430,7 +1438,8 @@ public function run() ]), 'locked' => true, 'sort' => 11, - 'width' => 2 + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_users', @@ -1442,13 +1451,14 @@ public function run() ]), 'locked' => true, 'sort' => 12, - 'width' => 2 + 'width' => 'half', + 'required' => true ], [ 'collection' => 'directus_users', 'field' => 'locale_options', 'type' => \Directus\Database\Schema\DataTypes::TYPE_JSON, - 'interface' => 'code', + 'interface' => 'json', 'locked' => true, 'hidden_browse' => true, 'hidden_detail' => true, @@ -1472,7 +1482,7 @@ public function run() 'locked' => true, 'readonly' => true, 'sort' => 15, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1483,7 +1493,7 @@ public function run() 'readonly' => true, 'hidden_detail' => true, 'sort' => 16, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', @@ -1495,7 +1505,7 @@ public function run() 'hidden_detail' => true, 'hidden_browse' => true, 'sort' => 17, - 'width' => 2 + 'width' => 'half' ], [ 'collection' => 'directus_users', diff --git a/migrations/db/seeds/SettingsSeeder.php b/migrations/db/seeds/SettingsSeeder.php new file mode 100644 index 0000000000..fb16a6393b --- /dev/null +++ b/migrations/db/seeds/SettingsSeeder.php @@ -0,0 +1,71 @@ + 'logo', + 'value' => '' + ], + [ + 'key' => 'color', + 'value' => 'darkest-gray', + ], + [ + 'key' => 'default_limit', + 'value' => '200' + ], + [ + 'key' => 'sort_null_last', + 'value' => '1' + ], + [ + 'key' => 'auto_sign_out', + 'value' => '60' + ], + [ + 'key' => 'youtube_api_key', + 'value' => '' + ], + [ + 'key' => 'trusted_proxies', + 'value' => '' + ], + [ + 'key' => 'thumbnail_dimensions', + 'value' => '200x200' + ], + [ + 'key' => 'thumbnail_quality_tags', + 'value' => '{"poor": 25, "good": 50, "better": 75, "best": 100}' + ], + [ + 'key' => 'thumbnail_actions', + 'value' => '{"contain":{"options":{"resizeCanvas":false,"position":"center","resizeRelative":false,"canvasBackground":"ccc"}},"crop":{"options":{"position":"center"}}}' + ], + [ + 'key' => 'thumbnail_cache_ttl', + 'value' => '86400' + ], + [ + 'key' => 'thumbnail_not_found_location', + 'value' => '' + ] + ]; + + $groups = $this->table('directus_settings'); + $groups->insert($data)->save(); + } +} diff --git a/migrations/upgrades/schemas/20190412122400_set_password_type_to_hash.php b/migrations/upgrades/schemas/20190412122400_set_password_type_to_hash.php new file mode 100644 index 0000000000..94b862d1c7 --- /dev/null +++ b/migrations/upgrades/schemas/20190412122400_set_password_type_to_hash.php @@ -0,0 +1,16 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + ['type' => \Directus\Database\Schema\DataTypes::TYPE_HASH], + ['collection' => 'directus_users', 'field' => 'password'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190412123000_use_file_interface.php b/migrations/upgrades/schemas/20190412123000_use_file_interface.php new file mode 100644 index 0000000000..5681c408fe --- /dev/null +++ b/migrations/upgrades/schemas/20190412123000_use_file_interface.php @@ -0,0 +1,16 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + ['interface' => 'file'], + ['interface' => 'single-file'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190412145800_set_o2m_options_roles.php b/migrations/upgrades/schemas/20190412145800_set_o2m_options_roles.php new file mode 100644 index 0000000000..86ac3fdc19 --- /dev/null +++ b/migrations/upgrades/schemas/20190412145800_set_o2m_options_roles.php @@ -0,0 +1,18 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + ['options' => json_encode([ + 'fields' => 'first_name,last_name' + ])], + ['collection' => 'directus_roles', 'field' => 'users'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190415125300_set_width.php b/migrations/upgrades/schemas/20190415125300_set_width.php new file mode 100644 index 0000000000..afce9fd775 --- /dev/null +++ b/migrations/upgrades/schemas/20190415125300_set_width.php @@ -0,0 +1,22 @@ +table('directus_fields'); + + $table->changeColumn('width', 'string', [ + 'limit' => 30, + 'null' => true, + 'default' => null, + ]); + + $this->execute("UPDATE directus_fields SET width = 'half' WHERE width = '1';"); + $this->execute("UPDATE directus_fields SET width = 'half' WHERE width = '2';"); + $this->execute("UPDATE directus_fields SET width = 'full' WHERE width = '3';"); + $this->execute("UPDATE directus_fields SET width = 'full' WHERE width = '4';"); + } +} diff --git a/migrations/upgrades/schemas/20190419154400_settings_fields.php b/migrations/upgrades/schemas/20190419154400_settings_fields.php new file mode 100644 index 0000000000..439c7e26b8 --- /dev/null +++ b/migrations/upgrades/schemas/20190419154400_settings_fields.php @@ -0,0 +1,151 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half-space', + 'note' => 'The URL where your app is hosted. The API will use this to direct your users to the correct login page.', + 'sort' => 4 + ], + ['collection' => 'directus_settings', 'field' => 'app_url'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'How many minutes before an idle user is signed out.', + 'sort' => 7 + ], + ['collection' => 'directus_settings', 'field' => 'auto_sign_out'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'How many minutes before an idle user is signed out.', + 'sort' => 2 + ], + ['collection' => 'directus_settings', 'field' => 'color'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'How many minutes before an idle user is signed out.', + 'sort' => 5 + ], + ['collection' => 'directus_settings', 'field' => 'default_limit'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'Your brand\'s logo.', + 'sort' => 3 + ], + ['collection' => 'directus_settings', 'field' => 'logo'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half-space', + 'sort' => 1 + ], + ['collection' => 'directus_settings', 'field' => 'project_name'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half-space', + 'note' => 'Put items with `null` for the value last when sorting.', + 'sort' => 6 + ], + ['collection' => 'directus_settings', 'field' => 'sort_null_last'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'Defines how the thumbnail will be generated based on the requested dimensions.', + 'sort' => 11 + ], + ['collection' => 'directus_settings', 'field' => 'thumbnail_actions'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => '`max-age` HTTP header of the thumbnail.', + 'sort' => 12 + ], + ['collection' => 'directus_settings', 'field' => 'thumbnail_cache_ttl'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'full', + 'note' => 'Allowed dimensions for thumbnails.', + 'sort' => 9 + ], + ['collection' => 'directus_settings', 'field' => 'thumbnail_dimensions'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'This image will be used when trying to generate a thumbnail with invalid options or an error happens on the server when creating the image.', + 'sort' => 13 + ], + ['collection' => 'directus_settings', 'field' => 'thumbnail_not_found_location'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'Allowed quality for thumbnails.', + 'sort' => 10 + ], + ['collection' => 'directus_settings', 'field' => 'thumbnail_quality_tags'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'width' => 'half', + 'note' => 'When provided, this allows more information to be collected for YouTube embeds.', + 'sort' => 8 + ], + ['collection' => 'directus_settings', 'field' => 'youtube_api'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190419161200_collection_notes.php b/migrations/upgrades/schemas/20190419161200_collection_notes.php new file mode 100644 index 0000000000..89a29be552 --- /dev/null +++ b/migrations/upgrades/schemas/20190419161200_collection_notes.php @@ -0,0 +1,55 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'note' => 'An internal description.' + ], + ['collection' => 'directus_collections', 'field' => 'note'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#managing-collections).' + ], + ['collection' => 'directus_collections', 'field' => 'managed'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#hidden).' + ], + ['collection' => 'directus_collections', 'field' => 'hidden'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'note' => '[Learn More](https://docs.directus.io/guides/collections.html#single).' + ], + ['collection' => 'directus_collections', 'field' => 'single'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'note' => 'The icon shown in the App\'s navigation sidebar.' + ], + ['collection' => 'directus_collections', 'field' => 'icon'] + )); + + } +} diff --git a/migrations/upgrades/schemas/20190419173000_misc_required_fields.php b/migrations/upgrades/schemas/20190419173000_misc_required_fields.php new file mode 100644 index 0000000000..459ecbde24 --- /dev/null +++ b/migrations/upgrades/schemas/20190419173000_misc_required_fields.php @@ -0,0 +1,126 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_users', 'field' => 'status'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_users', 'field' => 'timezone'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_users', 'field' => 'locale'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_users', 'field' => 'roles'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_roles', 'field' => 'name'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'required' => 1 + ], + ['collection' => 'directus_files', 'field' => 'filename'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 10 + ], + ['collection' => 'directus_files', 'field' => 'width'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 11 + ], + ['collection' => 'directus_files', 'field' => 'height'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 12 + ], + ['collection' => 'directus_files', 'field' => 'duration'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 13 + ], + ['collection' => 'directus_files', 'field' => 'filesize'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 8 + ], + ['collection' => 'directus_files', 'field' => 'uploaded_on'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'sort' => 9 + ], + ['collection' => 'directus_files', 'field' => 'uploaded_by'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'hidden_browse' => 1 + ], + ['collection' => 'directus_files', 'field' => 'checksum'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190422131600_use_json.php b/migrations/upgrades/schemas/20190422131600_use_json.php new file mode 100644 index 0000000000..ba2ee9d67c --- /dev/null +++ b/migrations/upgrades/schemas/20190422131600_use_json.php @@ -0,0 +1,144 @@ +execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_activity', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_activity_seen', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_collection_presets', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_collections', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_fields', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_files', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_folders', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_migrations', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_permissions', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_relations', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_revisions', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_roles', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_settings', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_user_roles', 'interface' => 'code'] + )); + + $this->execute(\Directus\phinx_update( + $this->getAdapter(), + 'directus_fields', + [ + 'interface' => 'json' + ], + ['collection' => 'directus_users', 'interface' => 'code'] + )); + } +} diff --git a/migrations/upgrades/schemas/20190426156200_set_nullable_value_field_settings_table.php b/migrations/upgrades/schemas/20190426156200_set_nullable_value_field_settings_table.php new file mode 100644 index 0000000000..1397b92022 --- /dev/null +++ b/migrations/upgrades/schemas/20190426156200_set_nullable_value_field_settings_table.php @@ -0,0 +1,15 @@ +table('directus_settings'); + + $table->changeColumn('value', 'text', [ + 'null' => true + ]); + } +} diff --git a/package.json b/package.json index 3c7653a71d..574445cb81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@directus/api", "private": true, - "version": "2.0.19", + "version": "2.1.0", "description": "Directus API", "main": "index.js", "repository": "directus/api", diff --git a/public/.htaccess b/public/.htaccess index 80d159d040..c13c18f45e 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,9 +1,6 @@ # Comment this line if you are getting: "Option SymLinksIfOwnerMatch not allowed here" error in Apache Options +SymLinksIfOwnerMatch -php_value upload_max_filesize 50M -php_value post_max_size 100M - # php5_module automatically handles HTTP_AUTHORIZATION headers, but fcgi_module does not. @@ -12,7 +9,6 @@ php_value post_max_size 100M - RewriteEngine On # Map all admin endpoints to the admin app (except static files) @@ -22,5 +18,9 @@ php_value post_max_size 100M # Map all other requests to invoke the API router (except static files) RewriteCond %{REQUEST_FILENAME} !-f RewriteRule !^admin index.php?%{QUERY_STRING} [L] - + + + php_value upload_max_filesize 50M + php_value post_max_size 100M + diff --git a/src/core/Directus/Application/Application.php b/src/core/Directus/Application/Application.php index 5e05d94af6..b112b92ceb 100644 --- a/src/core/Directus/Application/Application.php +++ b/src/core/Directus/Application/Application.php @@ -13,7 +13,7 @@ class Application extends App * * @var string */ - const DIRECTUS_VERSION = '2.0.19'; + const DIRECTUS_VERSION = '2.1.0'; /** * NOT USED diff --git a/src/core/Directus/Application/CoreServicesProvider.php b/src/core/Directus/Application/CoreServicesProvider.php index 023b1af1d9..f598ddedb3 100644 --- a/src/core/Directus/Application/CoreServicesProvider.php +++ b/src/core/Directus/Application/CoreServicesProvider.php @@ -182,16 +182,18 @@ protected function getEmitter() $cacheTableTagInvalidator = function ($tableName) use ($cachePool) { $cachePool->invalidateTags(['table_' . $tableName]); }; - - foreach (['item.update:after', 'collection.delete:after'] as $action) { + foreach (['item.create:after', 'item.delete:after', 'item.update:after', 'collection.update:after', 'collection.delete:after'] as $action) { $emitter->addAction($action, $cacheTableTagInvalidator); } - $emitter->addAction('item.delete:after', function ($tableName, $ids) use ($cachePool) { + $cacheEntityTagInvalidator = function ($tableName, $ids) use ($cachePool) { foreach ($ids as $id) { $cachePool->invalidateTags(['entity_' . $tableName . '_' . $id]); } - }); + }; + foreach (['item.delete:after', 'item.update:after'] as $action) { + $emitter->addAction($action, $cacheEntityTagInvalidator); + } $emitter->addAction('item.update.directus_permissions:after', function ($data) use ($container, $cachePool) { $acl = $container->get('acl'); @@ -538,7 +540,7 @@ protected function getEmitter() ]; // Authenticated user can see their private info // Admin can see all users private info - if (!$acl->isAdmin() && $userId !== $row['id']) { + if (!$acl->isAdmin() && $userId !== (int)$row['id']) { $omit = array_merge($omit, [ 'token', 'email_notifications', diff --git a/src/core/Directus/Application/Http/Middleware/CorsMiddleware.php b/src/core/Directus/Application/Http/Middleware/CorsMiddleware.php index fc4c64199a..780c47c30c 100644 --- a/src/core/Directus/Application/Http/Middleware/CorsMiddleware.php +++ b/src/core/Directus/Application/Http/Middleware/CorsMiddleware.php @@ -37,7 +37,7 @@ class CorsMiddleware extends AbstractMiddleware 'Authorization', ], 'exposed_headers' => [], - 'max_age' => null, + 'max_age' => 500, 'credentials' => false, ]; diff --git a/src/core/Directus/Authentication/Provider.php b/src/core/Directus/Authentication/Provider.php index 2be8bbffef..ac025f6265 100644 --- a/src/core/Directus/Authentication/Provider.php +++ b/src/core/Directus/Authentication/Provider.php @@ -71,7 +71,7 @@ public function __construct(UserProviderInterface $userProvider, array $options throw new Exception('auth: secret key is required and it must be a string'); } - $ttl = ArrayUtils::get($options, 'ttl', 5); + $ttl = ArrayUtils::get($options, 'ttl', 20); if (!is_numeric($ttl)) { throw new Exception('ttl must be a number'); } @@ -370,7 +370,7 @@ public function generateRequestToken(UserInterface $user) 'type' => 'request_token', 'id' => (int) $user->getId(), // 'group' => (int) $user->getGroupId(), - 'exp' => time() + (5 * DateTimeUtils::MINUTE_IN_SECONDS), + 'exp' => time() + (20 * DateTimeUtils::MINUTE_IN_SECONDS), 'url' => \Directus\get_url(), 'project' => \Directus\get_api_project_from_request() ]; diff --git a/src/core/Directus/Console/Common/User.php b/src/core/Directus/Console/Common/User.php index b7405ab1e9..46d533d0f1 100644 --- a/src/core/Directus/Console/Common/User.php +++ b/src/core/Directus/Console/Common/User.php @@ -27,6 +27,28 @@ public function __construct($base_path) $this->usersTableGateway = new TableGateway('directus_users', $this->db); } + /** + * Check the existance of user in the system + * + * The function will check the user of given their e-mail address exist in + * the system or not. + */ + public function userExists($email) + { + try { + $rowset = $this->usersTableGateway->select([ + 'email' => $email + ]); + if ($rowset->count() > 0) { + return true; + } + return false; + } catch (\PDOException $ex) { + return false; + } + } + + /** * Change the password of a user given their e-mail address * diff --git a/src/core/Directus/Console/Modules/InstallModule.php b/src/core/Directus/Console/Modules/InstallModule.php index 6c16508149..bcb00e8b38 100644 --- a/src/core/Directus/Console/Modules/InstallModule.php +++ b/src/core/Directus/Console/Modules/InstallModule.php @@ -201,12 +201,17 @@ public function cmdInstall($args, $extra) $user = new User($directus_path); try { $hasEmail = ArrayUtils::has($data, 'user_email'); - if ($hasEmail) { - $user->changeEmail(1, $data['user_email']); - } - - if ($hasEmail && ArrayUtils::has($data, 'user_password')) { - $user->changePassword($data['user_email'], $data['user_password']); + if ($hasEmail && !$user->userExists($data['user_email'])) { + InstallerUtils::addDefaultUser($directus_path, $data, $projectName); + }else{ + //TODO: Verify this method is required or not! + if ($hasEmail) { + $user->changeEmail(1, $data['user_email']); + } + + if ($hasEmail && ArrayUtils::has($data, 'user_password')) { + $user->changePassword($data['user_email'], $data['user_password']); + } } } catch (UserUpdateException $ex) { throw new CommandFailedException('Error changing admin e-mail' . ': ' . $ex->getMessage()); diff --git a/src/core/Directus/Database/Exception/InvalidFieldException.php b/src/core/Directus/Database/Exception/InvalidFieldException.php index 5c0ee229bf..189b008956 100644 --- a/src/core/Directus/Database/Exception/InvalidFieldException.php +++ b/src/core/Directus/Database/Exception/InvalidFieldException.php @@ -8,9 +8,9 @@ class InvalidFieldException extends UnprocessableEntityException { const ERROR_CODE = 202; - public function __construct($field) + public function __construct($field, $collection) { - $message = sprintf('Invalid field "%s"', $field); + $message = sprintf('Invalid field "%s" in "%s"', $field, $collection); parent::__construct($message); } diff --git a/src/core/Directus/Database/Query/Builder.php b/src/core/Directus/Database/Query/Builder.php index c5815d0f8c..d1a331da5d 100644 --- a/src/core/Directus/Database/Query/Builder.php +++ b/src/core/Directus/Database/Query/Builder.php @@ -267,9 +267,9 @@ public function orWhereIn($column, $values, $not = false) * * @return Builder */ - public function whereNotIn($column, array $values) + public function whereNotIn($column, array $values, $not = false, $logical = 'and') { - return $this->whereIn($column, $values, true); + return $this->whereIn($column, $values, true, $logical); } public function whereBetween($column, array $values, $not = false, $logical = 'and') @@ -277,9 +277,9 @@ public function whereBetween($column, array $values, $not = false, $logical = 'a return $this->where($column, 'between', $values, $not, $logical); } - public function whereNotBetween($column, array $values) + public function whereNotBetween($column, array $values, $not = false, $logical = 'and') { - return $this->whereBetween($column, $values, true); + return $this->whereBetween($column, $values, true, $logical); } public function whereEqualTo($column, $value, $not = false, $logical = 'and') @@ -292,29 +292,29 @@ public function orWhereEqualTo($column, $value, $not = false) return $this->where($column, '=', $value, $not, 'or'); } - public function whereNotEqualTo($column, $value) + public function whereNotEqualTo($column, $value, $not = false, $logical = 'and') { - return $this->whereEqualTo($column, $value, true); + return $this->whereEqualTo($column, $value, true, $logical); } - public function whereLessThan($column, $value) + public function whereLessThan($column, $value, $not = false, $logical = 'and') { - return $this->where($column, '<', $value); + return $this->where($column, '<', $value, $not, $logical); } - public function whereLessThanOrEqual($column, $value) + public function whereLessThanOrEqual($column, $value, $not = false, $logical = 'and') { - return $this->where($column, '<=', $value); + return $this->where($column, '<=', $value, $not, $logical); } - public function whereGreaterThan($column, $value) + public function whereGreaterThan($column, $value, $not = false, $logical = 'and') { - return $this->where($column, '>', $value); + return $this->where($column, '>', $value, $not, $logical); } - public function whereGreaterThanOrEqual($column, $value) + public function whereGreaterThanOrEqual($column, $value, $not = false, $logical = 'and') { - return $this->where($column, '>=', $value); + return $this->where($column, '>=', $value, $not, $logical); } public function whereNull($column, $not = false, $logical = 'and') @@ -342,9 +342,9 @@ public function orWhereLike($column, $value, $not = false) return $this->whereLike($column, $value, $not, 'or'); } - public function whereNotLike($column, $value) + public function whereNotLike($column, $value, $not = false, $logical = 'and') { - return $this->whereLike($column, $value, true); + return $this->whereLike($column, $value, true, $logical); } public function whereAll($column, $table, $columnLeft, $columnRight, $values) @@ -741,7 +741,7 @@ protected function getIdentifier($column) $platform = $this->getConnection()->getPlatform(); $table = $this->getFrom(); - if (strpos($column, $platform->getIdentifierSeparator()) === false) { + if (is_string ($column) && strpos($column, $platform->getIdentifierSeparator()) === false) { $column = implode($platform->getIdentifierSeparator(), [$table, $column]); } diff --git a/src/core/Directus/Database/Schema/DataTypes.php b/src/core/Directus/Database/Schema/DataTypes.php index 4e237f39aa..ea774ac284 100644 --- a/src/core/Directus/Database/Schema/DataTypes.php +++ b/src/core/Directus/Database/Schema/DataTypes.php @@ -338,6 +338,18 @@ public static function isSystemDateTimeType($type) return in_array(strtolower($type), static::getSystemDateTimeTypes()); } + /** + * Checks whether or not the given type is status type + * + * @param string $type + * + * @return bool + */ + public static function isStatusType($type) + { + return strtolower($type) === static::TYPE_STATUS; + } + /** * Returns all the unique data types * diff --git a/src/core/Directus/Database/Schema/SchemaFactory.php b/src/core/Directus/Database/Schema/SchemaFactory.php index f3c273dfd3..bf8623d3fc 100644 --- a/src/core/Directus/Database/Schema/SchemaFactory.php +++ b/src/core/Directus/Database/Schema/SchemaFactory.php @@ -31,6 +31,8 @@ use Zend\Db\Sql\Ddl\Constraint\UniqueKey; use Zend\Db\Sql\Ddl\CreateTable; use Zend\Db\Sql\Sql; +use Zend\Db\Sql\Ddl\Column\AbstractLengthColumn; +use Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn; class SchemaFactory { @@ -66,7 +68,7 @@ public function createTable($name, array $columnsData = []) foreach ($columnsData as $column) { if (ArrayUtils::get($column, 'primary_key', false)) { $table->addConstraint(new PrimaryKey($column['field'])); - } else if (ArrayUtils::get($column, 'unique') == true) { + } elseif (ArrayUtils::get($column, 'unique') == true) { $table->addConstraint(new UniqueKey($column['field'])); } } @@ -104,7 +106,8 @@ public function alterTable($name, array $data) if (ArrayUtils::get($options, 'primary_key') == true) { $table->addConstraint(new PrimaryKey($column->getName())); - } if (ArrayUtils::get($options, 'unique') == true) { + } + if (ArrayUtils::get($options, 'unique') == true) { $table->addConstraint(new UniqueKey($column->getName())); } } @@ -121,7 +124,8 @@ public function alterTable($name, array $data) if (ArrayUtils::get($options, 'primary_key') == true) { $table->addConstraint(new PrimaryKey($column->getName())); - } if (ArrayUtils::get($options, 'unique') == true) { + } + if (ArrayUtils::get($options, 'unique') == true) { $table->addConstraint(new UniqueKey($column->getName())); } } @@ -131,7 +135,13 @@ public function alterTable($name, array $data) $table->dropColumn($column); } - return $table; + //BUGFIX: Do nothing if there's nothing to do + return !empty($table->getRawState(AlterTable::ADD_COLUMNS)) + || !empty($table->getRawState(AlterTable::ADD_CONSTRAINTS)) + || !empty($table->getRawState(AlterTable::CHANGE_COLUMNS)) + || !empty($table->getRawState(AlterTable::DROP_COLUMNS)) + || !empty($table->getRawState(AlterTable::DROP_CONSTRAINTS)) + ? $table : false; } /** @@ -190,7 +200,7 @@ public function createColumn($name, array $data) $parts = !is_array($length) ? explode(',', $length) : $length; $column->setDigits($parts[0]); $column->setDecimal(isset($parts[1]) ? $parts[1] : 0); - } else if ($column instanceof AbstractLengthColumn || $column instanceof CollectionLength) { + } elseif ($column instanceof AbstractLengthColumn || $column instanceof CollectionLength) { $column->setLength($length); } else { $column->setOption('length', $length); @@ -212,15 +222,14 @@ public function createColumn($name, array $data) * * @return \Zend\Db\Adapter\Driver\StatementInterface|\Zend\Db\ResultSet\ResultSet */ - public function buildTable(AbstractSql $table) + public function buildTable(AbstractSql $table,$charset="") { $connection = $this->schemaManager->getSource()->getConnection(); $sql = new Sql($connection); //WORKAROUND ZendDB doesn't know anything about PostgreSQL for instance, we might need to override some of the table specifications depending on the RDBMS used //We monkey-path Zend-DB behaviour here and not through its own source repository with a decorator - $sqlFixed = $this->schemaManager->getSource()->buildSql($table, $sql); - $connection = $this->schemaManager->getSource()->getConnection(); + $sqlFixed = $this->schemaManager->getSource()->buildSql($table, $sql, $charset); // TODO: Allow charset and comment return $connection->query( $sqlFixed, diff --git a/src/core/Directus/Database/Schema/Sources/AbstractSchema.php b/src/core/Directus/Database/Schema/Sources/AbstractSchema.php index f2044011d7..168cf21fd9 100644 --- a/src/core/Directus/Database/Schema/Sources/AbstractSchema.php +++ b/src/core/Directus/Database/Schema/Sources/AbstractSchema.php @@ -2,6 +2,7 @@ namespace Directus\Database\Schema\Sources; +use Directus\Database\Query\Builder; use Directus\Database\Schema\DataTypes; use Directus\Database\Schema\Object\Field; use Directus\Util\ArrayUtils; @@ -213,10 +214,11 @@ public function getNextGeneratedId($abstractTableGateway, $table, $field) * * @param AbstractSql|AlterTable|CreateTable $table * @param Sql $sql + * @param String $charset * * @return String */ - public function buildSql($table, $sql) + public function buildSql($table, $sql, $charset) { //Do nothing return $sql->buildSqlString($table); @@ -241,4 +243,15 @@ public function transformField(array $field) } return $transformedField; } + + /** + * get a new SQL Builder + * @param AdapterInterface $adapter + * + * @return Builder + */ + public function getBuilder($adapter) + { + return new Builder($adapter); + } } diff --git a/src/core/Directus/Database/Schema/Sources/MySQLSchema.php b/src/core/Directus/Database/Schema/Sources/MySQLSchema.php index 783f137908..fe04e822ab 100644 --- a/src/core/Directus/Database/Schema/Sources/MySQLSchema.php +++ b/src/core/Directus/Database/Schema/Sources/MySQLSchema.php @@ -15,6 +15,7 @@ use Zend\Db\Sql\Sql; use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\Where; +use Zend\Db\Sql\Ddl\CreateTable; use Zend\Db\Sql\Ddl\Column\AbstractLengthColumn; use Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn; use Zend\Db\Sql\Ddl\Column\BigInteger; @@ -216,9 +217,9 @@ public function getAllFields(array $params = []) ]); if (isset($params['collection'])) { - $selectOne->where([ - 'SF.TABLE_NAME' => $params['collection'] - ]); + $where = $selectOne->where->nest(); + $where->equalTo(new Expression('BINARY SF.TABLE_NAME'), $params['collection']); + $where->unnest(); } if (isset($params['field'])) { @@ -692,6 +693,8 @@ public function getTypesRequireLength() 'varbinary', 'enum', 'set', + 'decimal', + 'char' ]; } @@ -852,6 +855,24 @@ public function createColumnFromDataType($name, $type) return $column; } + /** + * Fix defaultZendDB choices if applicable + * + * @param AbstractSql|AlterTable|CreateTable|DropTable $table + * @param Sql $sql + * @param String $charset + * + * @return String + */ + public function buildSql($table, $sql, $charset) + { + $query = parent::buildSql($table, $sql, $charset); + if ($table instanceof CreateTable) { + $query = !empty($charset) ? $query."charset = ".$charset: $query; + } + return $query; + } + /** * Transform if needed the default value of a field * @param array $field diff --git a/src/core/Directus/Database/Schema/Sources/PostgresSchema.php b/src/core/Directus/Database/Schema/Sources/PostgresSchema.php index 2d98c864fd..8dd25076a8 100644 --- a/src/core/Directus/Database/Schema/Sources/PostgresSchema.php +++ b/src/core/Directus/Database/Schema/Sources/PostgresSchema.php @@ -20,6 +20,7 @@ use function Directus\get_directus_setting; use function Directus\compact_sort_to_array; use Directus\Database\Schema\Sources\AbstractSchema; +use Directus\Database\Schema\Sources\Query\PostgresBuilder; use Directus\Database\Schema\Sources\Expression\PostgresChangeColumn; use Directus\Database\Schema\Sources\Expression\PostgresAddIntegerColumn; @@ -849,7 +850,14 @@ public function createColumnFromDataType($name, $type) break; case 'bool': case 'boolean': - $column = new \Zend\Db\Sql\Ddl\Column\Boolean($name); + //For unknown reasons, Zend-db decided that boolean must be non-null; we break this rule and let the application choose + $column = new class($name) extends \Zend\Db\Sql\Ddl\Column\Boolean { + public function setNullable($nullable) + { + $this->isNullable = (bool) $nullable; + return $this; + } + }; break; case 'smallserial': case 'serial2': //alias @@ -896,10 +904,11 @@ public function createColumnFromDataType($name, $type) * * @param AbstractSql|AlterTable|CreateTable|DropTable $table * @param Sql $sql + * @param String $charset * * @return String */ - public function buildSql($table, $sql) + public function buildSql($table, $sql, $charset) { if ($table instanceof AlterTable) { //Zend-Db Specifications are protected :( @@ -934,7 +943,7 @@ public function buildSql($table, $sql) }; $sealBreaker->call($table); } - return parent::buildSql($table, $sql); + return parent::buildSql($table, $sql, $charset); } /** @@ -976,4 +985,15 @@ public function transformField(array $field) } return $transformedField; } + + /** + * get a new SQL Builder + * @param AdapterInterface $adapter + * + * @return Builder + */ + public function getBuilder($adapter) + { + return new PostgresBuilder($adapter); + } } diff --git a/src/core/Directus/Database/Schema/Sources/Query/PostgresBuilder.php b/src/core/Directus/Database/Schema/Sources/Query/PostgresBuilder.php new file mode 100644 index 0000000000..49d1ad77b6 --- /dev/null +++ b/src/core/Directus/Database/Schema/Sources/Query/PostgresBuilder.php @@ -0,0 +1,144 @@ +connection); + } + + protected function buildConditionExpression($condition) + { + $not = ArrayUtils::get($condition, 'not', false) === true; + $notChar = ''; + if ($not === true) { + $notChar = $condition['operator'] === '=' ? '!' : 'n'; + } + + $operator = $notChar . $condition['operator']; + + $column = $condition['column']; + $identifier = $this->getIdentifier($column); + $value = $condition['value']; + + if ($value instanceof Builder) { + $value = $value->buildSelect(); + } + + switch ($operator) { + case 'in': + $expression = new In($identifier, $value); + break; + case 'nin': + $expression = new NotIn($identifier, $value); + break; + case 'like': + $sealBreaker = function () { + //PostgreSQL is not like MySQL, you first need to cast teh column to do a LIKE comparison + $this->specification = '%1$s::TEXT LIKE %2$s'; + return $this; + }; + $expression = $sealBreaker->call(new Like($identifier, $value)); + break; + case 'nlike': + $sealBreaker = function () { + //PostgreSQL is not like MySQL, you first need to cast teh column to do a LIKE comparison + $this->specification = '%1$s::TEXT NOT LIKE %2$s'; + return $this; + }; + $expression = $sealBreaker->call(new NotLike($identifier, $value)); + break; + case 'null': + $expression = new IsNull($identifier); + break; + case 'nnull': + $expression = new IsNotNull($identifier); + break; + case 'between': + $expression = new Between($identifier, array_shift($value), array_pop($value)); + break; + case 'nbetween': + $expression = new NotBetween($identifier, array_shift($value), array_pop($value)); + break; + default: + $expression = new Operator($identifier, $operator, $value); + } + + return $expression; + } + + public function whereAll($column, $table, $columnLeft, $columnRight, $values) + { + if ($columnLeft === null) { + $relation = new PostgresOneToManyRelation($this, $column, $table, $columnRight, $this->getFrom()); + } else { + $relation = new PostgresManyToManyRelation($this, $table, $columnLeft, $columnRight); + } + + $relation->all($values); + + return $this->whereIn($column, $relation); + } + + public function whereHas($column, $table, $columnLeft, $columnRight, $count = 1, $not = false) + { + if (is_null($columnLeft)) { + $relation = new PostgresOneToManyRelation($this, $column, $table, $columnRight, $this->getFrom()); + } else { + $relation = new PostgresManyToManyRelation($this, $table, $columnLeft, $columnRight); + } + + // If checking if has 0, this case will be the opposite + // has = 0, NOT IN the record that has more than 0 + // not has = 0, IN the record that has more than 0 + if ($count < 1) { + $not = !$not; + } + + $relation->has($count); + + return $this->whereIn($column, $relation, $not); + } + + public function whereRelational($column, $table, $columnLeft, $columnRight = null, \Closure $callback = null, $logical = 'and') + { + if (is_callable($columnRight)) { + // $column: Relational Column + // $table: Related table + // $columnRight: Related table that points to $column + $callback = $columnRight; + $columnRight = $columnLeft; + $columnLeft = null; + $relation = new PostgresManyToOneRelation($this, $columnRight, $table); + } else if (is_null($columnLeft)) { + $relation = new PostgresOneToManyRelation($this, $column, $table, $columnRight, $this->getFrom()); + } else { + $relation = new PostgresManyToManyRelation($this, $table, $columnLeft, $columnRight); + } + + call_user_func($callback, $relation); + + return $this->whereIn($column, $relation, false, $logical); + } +} diff --git a/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToManyRelation.php b/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToManyRelation.php new file mode 100644 index 0000000000..5a03dd7f7c --- /dev/null +++ b/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToManyRelation.php @@ -0,0 +1,45 @@ +getConnection()); + + $this->parentBuilder = $builder; + $this->table = $table; + $this->columnLeft = $columnLeft; + $this->columnRight = $columnRight; + + $this->from($table); + } + + public function all(array $values) + { + $this->columns([$this->columnLeft]); + $this->whereIn($this->columnRight, $values); + $this->groupBy($this->columnLeft); + $this->having(new Expression('COUNT(*) = ?', count($values))); + + return $this; + } + + public function has($count = 1) + { + $this->columns([$this->columnLeft]); + $this->groupBy($this->columnLeft); + $this->having(new Expression('COUNT(*) >= ?', (int) $count)); + + return $this; + } +} \ No newline at end of file diff --git a/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToOneRelation.php b/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToOneRelation.php new file mode 100644 index 0000000000..20c92c8453 --- /dev/null +++ b/src/core/Directus/Database/Schema/Sources/Query/PostgresManyToOneRelation.php @@ -0,0 +1,25 @@ +getConnection()); + + $this->parentBuilder = $builder; + $this->column = $column; + $this->relatedTable = $relatedTable; + + $this->columns([$this->column]); + $this->from($this->relatedTable); + } +} diff --git a/src/core/Directus/Database/Schema/Sources/Query/PostgresOneToManyRelation.php b/src/core/Directus/Database/Schema/Sources/Query/PostgresOneToManyRelation.php new file mode 100644 index 0000000000..7b55841215 --- /dev/null +++ b/src/core/Directus/Database/Schema/Sources/Query/PostgresOneToManyRelation.php @@ -0,0 +1,65 @@ +getConnection()); + + $this->parentBuilder = $builder; + $this->column = $column; + $this->table = $table; + $this->columnRight = $columnRight; + $this->relatedTable = $relatedTable; + + $this->columns([$this->column]); + $this->from($relatedTable); + $on = sprintf('%s.%s = %s.%s', $this->relatedTable, $this->column, $this->table, $this->columnRight); + $this->join($this->table, $on, [$this->columnRight], 'right'); + } + + public function all(array $values) + { + $this->columns([]); + $this->whereIn($this->table . '.' . $this->column, $values); + $this->groupBy($this->columnRight); + $this->having(new Expression('COUNT(*) = ?', count($values))); + + return $this; + } + + public function has($count = 1) + { + $this->columns([]); + $this->groupBy($this->columnRight); + $this->having(new Expression('COUNT(*) >= ?', (int) $count)); + + return $this; + } + + public function whereLike($column, $value, $not = false, $logical = 'and') + { + $this->columns([]); + parent::whereLike($this->table . '.' . $column, $value, $not, $logical); + + return $this; + } + + public function orWhereLike($column, $value, $not = false) + { + $this->whereLike($column, $value, $not, 'or'); + + return $this; + } +} diff --git a/src/core/Directus/Database/Schema/Sources/SchemaInterface.php b/src/core/Directus/Database/Schema/Sources/SchemaInterface.php index e67b620b1e..dd91f291b5 100644 --- a/src/core/Directus/Database/Schema/Sources/SchemaInterface.php +++ b/src/core/Directus/Database/Schema/Sources/SchemaInterface.php @@ -356,10 +356,11 @@ public function createColumnFromDataType($name, $type); * * @param AbstractSql|AlterTable|CreateTable $table * @param Sql $sql + * @param String $charset * * @return String */ - public function buildSql($table, $sql); + public function buildSql($table, $sql, $charset); /** * Transform if needed the default value of a field @@ -368,4 +369,12 @@ public function buildSql($table, $sql); * @return array $field */ public function transformField(array $field); + + /** + * get a new SQL Builder + * @param AdapterInterface $adapter + * + * @return Builder + */ + public function getBuilder($adapter); } diff --git a/src/core/Directus/Database/SchemaService.php b/src/core/Directus/Database/SchemaService.php index f14d889a82..e86e8ef779 100644 --- a/src/core/Directus/Database/SchemaService.php +++ b/src/core/Directus/Database/SchemaService.php @@ -352,8 +352,10 @@ public static function getRelatedCollectionName($tableName, $columnName) $tableObject = static::getCollection($tableName); $columnObject = $tableObject->getField($columnName); - - return $columnObject->getRelationship()->getCollectionOne(); + if($columnObject->getRelationship()->getType() == FieldRelationship::ONE_TO_MANY) + return $columnObject->getRelationship()->getCollectionMany(); + else + return $columnObject->getRelationship()->getCollectionOne(); } /** diff --git a/src/core/Directus/Database/TableGateway/BaseTableGateway.php b/src/core/Directus/Database/TableGateway/BaseTableGateway.php index 338bd9b235..a5ab9d0796 100644 --- a/src/core/Directus/Database/TableGateway/BaseTableGateway.php +++ b/src/core/Directus/Database/TableGateway/BaseTableGateway.php @@ -388,6 +388,27 @@ public function addRecordByArray(array $recordData) $TableGateway->ignoreFilters(); } + // NOTE: This is a dirty fix for https://github.com/directus/api/issues/750 + // Currently, the whole file content is being read to a base64 string which is being added + // to the $recordData array. If this data string is too large, the insert() call below this + // if statement will 500 error out without any error logs or anything. I'm assuming it's the + // php process running out of memory. When I removed the data key for every file, I noticed + // that the thumbnailer stopped working. For now, this if statement will check if the record + // contains both a filename and a data key, indicating that it's a file. If the length of the + // data key is over 25 million characters, we stop passing on the data key. As mentioned, + // this data string is base64 encoded, so this 25 million number doesn't translate very well + // into bytes. I believe it's somewhere in the 20~25MB range, which should be plenty for + // photos, which are the only usecase for the thumbnailer. + // TODO: Move this somewhere more sensible, and don't read the whole file contents into memory + // in the first place. + if ( + array_key_exists('filename', $recordData) && + array_key_exists('data', $recordData) && + strlen($recordData['data']) > 25000000 + ) { + $recordData = ['filename' => $recordData['filename']]; + } + $TableGateway->insert($recordData); if (static::$emitter && $listenerId) { @@ -675,7 +696,7 @@ protected function addVirtualColumn($tableName, $columnData) public function castFloatIfNumeric(&$value, $key) { if ($key != 'table_name') { - $value = is_numeric($value) ? (float)$value : $value; + $value = is_numeric($value) && preg_match('/^-?(?:\d+|\d*\.\d+)$/',$value) ? (float)$value : $value; } } @@ -913,11 +934,12 @@ protected function executeDelete(Delete $delete) if ($pk = $this->primaryKeyFieldName) { $select = $this->sql->select(); $select->where($deleteState['where']); - $select->columns([$pk]); $results = parent::executeSelect($select); + $deletedObject = []; foreach($results as $result) { $ids[] = $result['id']; + $deletedObject[$result['id']] = $result->toArray(); } } @@ -943,7 +965,7 @@ protected function executeDelete(Delete $delete) } foreach ($ids as $id) { - $deleteData = ['id' => $id]; + $deleteData = $deletedObject[$id]; $this->runHook('item.delete', [$deleteTable, $deleteData]); $this->runHook('item.delete:after', [$deleteTable, $deleteData]); $this->runHook('item.delete.' . $deleteTable, [$deleteData]); diff --git a/src/core/Directus/Database/TableGateway/RelationalTableGateway.php b/src/core/Directus/Database/TableGateway/RelationalTableGateway.php index 4b0cc7bcca..d9707ef8e7 100644 --- a/src/core/Directus/Database/TableGateway/RelationalTableGateway.php +++ b/src/core/Directus/Database/TableGateway/RelationalTableGateway.php @@ -820,6 +820,11 @@ public function getItems(array $params = []) { ArrayUtils::remove($params, 'id'); + // Check if single param is set then convert it into boolean + if (ArrayUtils::get($params, 'single')) { + $params['single'] = json_decode(strtolower(ArrayUtils::get($params, 'single'))); + } + return $this->fetchData($params); } @@ -991,7 +996,7 @@ public function fetchItems(array $params = [], \Closure $queryCallback = null) // TODO: Check for all collections + fields permission/existence before querying // TODO: Create a new TableGateway Query Builder based on Query\Builder - $builder = new Builder($this->getAdapter()); + $builder = $this->getSchemaManager()->getSource()->getBuilder($this->getAdapter()); $builder->from($this->getTable()); $selectedFields = $this->getSelectedNonAliasFields($fields ?: ['*']); @@ -1113,10 +1118,9 @@ public function fetchItems(array $params = [], \Closure $queryCallback = null) $results = array_values($results); } - if (ArrayUtils::has($params, 'single')) { + if (ArrayUtils::get($params, 'single')) { $results = reset($results); } - return $results ? $results : []; } @@ -1134,7 +1138,7 @@ protected function fetchData(array $params = []) $single = ArrayUtils::get($params, 'single'); $idsCount = is_array($id) ? count($id) : 1; - if (!$single && $id && $idsCount == 1) { + if (!$single && $id !== null && $idsCount == 1) { $single = $params['single'] = true; } @@ -1197,7 +1201,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) continue; } - $columnList = $columns = explode('.', $column); + $columnList = $filterColumns = explode('.', $column); $columnsTable = [ $this->getTable() ]; @@ -1205,11 +1209,13 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $nextColumn = array_shift($columnList); $nextTable = $this->getTable(); $relational = SchemaService::hasRelationship($nextTable, $nextColumn); - + $relationalTables = []; while ($relational) { + $relationalTables[$nextColumn] = $nextTable; $nextTable = SchemaService::getRelatedCollectionName($nextTable, $nextColumn); $nextColumn = array_shift($columnList); - + if(empty($nextColumn)) + break; // Confirm the user has permission to all chained (dot) fields if ($this->acl && !$this->acl->canRead($nextTable)) { throw new Exception\ForbiddenFieldAccessException($nextColumn); @@ -1218,7 +1224,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $relational = SchemaService::hasRelationship($nextTable, $nextColumn); $columnsTable[] = $nextTable; } - + // if one of the column in the list has not relationship // it will break the loop before going over all the columns // which we will call this as column not found @@ -1229,7 +1235,23 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) // Remove the original filter column with dot-notation unset($filters[$column]); - + + //Prepare relational data for all the fields + $columnRelationalData = []; + foreach($filterColumns as $filterColumn){ + if(isset($relationalTables[$filterColumn])){ + $collection = $this->getTableSchema($relationalTables[$filterColumn]); + $fieldRelation = $collection->getField($filterColumn)->getRelationship(); + $columnRelationalData[$filterColumn] = [ + "type" => $fieldRelation->getType(), + "collection_many" => $fieldRelation->getCollectionMany(), + "field_many" => $fieldRelation->getFieldMany(), + "collection_one" => $fieldRelation->getCollectionOne(), + "field_one" => $fieldRelation->getFieldOne() + ]; + } + } + // Reverse all the columns from comments.author.id to id.author.comments // To filter from the most deep relationship to their parents $columns = explode('.', \Directus\column_identifier_reverse($column)); @@ -1243,23 +1265,40 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $column = array_shift($columns); $table = array_shift($columnsTable); - $query = new Builder($this->getAdapter()); + $query = $this->getSchemaManager()->getSource()->getBuilder($this->getAdapter()); $mainTableObject = $this->getTableSchema($table); - $query->columns([$mainTableObject->getPrimaryField()->getName()]); + $selectColumn = $mainTableObject->getPrimaryField()->getName(); + + //check if column type is alias and relationship is O2M + $previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:''; + if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $selectColumn = $columnRelationalData[$previousRelation]['field_many']; + } + + //get last relationship + if ($mainColumn && !empty($mainColumn) && $columnRelationalData[$mainColumn]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $mainColumn = $mainTableObject->getPrimaryField()->getName(); + } + $query->columns([$selectColumn]); + $query->from($table); $this->doFilter($query, $column, $condition, $table); - $index = 0; foreach ($columns as $key => $column) { ++$index; $oldQuery = $query; - $query = new Builder($this->getAdapter()); + $query = $this->getSchemaManager()->getSource()->getBuilder($this->getAdapter()); $collection = $this->getTableSchema($columnsTable[$key]); $field = $collection->getField($column); $selectColumn = $collection->getPrimaryField()->getName(); + //check if column type is alias and relationship is O2M + $previousRelation = isset($filterColumns[array_search($column, $filterColumns)-1])?$filterColumns[array_search($column, $filterColumns)-1]:''; + if ($previousRelation && $columnRelationalData[$previousRelation]['type'] == \Directus\Database\Schema\Object\FieldRelationship::ONE_TO_MANY) { + $selectColumn = $columnRelationalData[$previousRelation]['field_many']; + } $table = $columnsTable[$key]; if ($field->isAlias()) { @@ -1278,10 +1317,10 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) // TODO: Make all this whereIn duplication into a function // TODO: Can we make the O2M simpler getting the parent id from itself // right now is creating one unnecessary select - if ($field->isOneToMany()) { + /*if ($field->isOneToMany()) { $mainColumn = $collection->getPrimaryField()->getName(); $oldQuery = $query; - $query = new Builder($this->getAdapter()); + $query = $this->getSchemaManager()->getSource()->getBuilder($this->getAdapter()); $selectColumn = $column = $relationship->getFieldOne(); $table = $relationship->getCollectionOne(); @@ -1291,7 +1330,7 @@ protected function parseDotFilters(Builder $mainQuery, array $filters) $column, $oldQuery ); - } + }*/ $this->doFilter( $mainQuery, @@ -1317,7 +1356,7 @@ protected function doFilter(Builder $query, $column, $condition, $table) ); if (!$field) { - throw new Exception\InvalidFieldException($fieldName); + throw new Exception\InvalidFieldException($fieldName, $table); } $condition = $this->parseCondition($condition); @@ -1406,7 +1445,23 @@ protected function doFilter(Builder $query, $column, $condition, $table) } // TODO: Move this into QueryBuilder if possible - if (in_array($operator, ['like']) && $field->isManyToOne()) { + if($field->isOneToMany()){ + $relationship = $field->getRelationship(); + $relatedTable = $relationship->getCollectionMany(); + $relatedRightColumn = $relationship->getFieldMany(); + $tableSchema = SchemaService::getCollection($relatedTable); + $relatedTableColumns = $tableSchema->getFields(); + + $query->orWhereRelational($this->primaryKeyFieldName, $relatedTable, null, $relatedRightColumn, function(Builder $query) use ($column, $relatedTable, $relatedTableColumns, $value) { + foreach ($relatedTableColumns as $column) { + $isNumeric = $this->getSchemaManager()->isNumericType($column->getType()); + $isString = $this->getSchemaManager()->isStringType($column->getType()); + if (!$column->isAlias() && ($isNumeric || $isString)) { + $query->orWhereLike($column->getName(), $value); + } + } + }); + } else if(in_array($operator, ['like']) && $field->isManyToOne()) { $relatedTable = $field->getRelationship()->getCollectionOne(); $tableSchema = SchemaService::getCollection($relatedTable); $relatedTableColumns = $tableSchema->getFields(); @@ -1452,9 +1507,21 @@ protected function shouldIgnoreQueryFilter($operator, $value) */ protected function processFilter(Builder $query, array $filters = []) { - $filters = $this->parseDotFilters($query, $filters); - - foreach ($filters as $column => $conditions) { + //Logic for blacklisted fields + $blackListStatuses = []; + foreach($filters as $column => $conditions){ + $column = explode('.', $column); + $column = array_shift($column); + $fieldReadBlackListDetails = $this->acl->getStatusesOnReadFieldBlacklist($this->getTable(),$column); + if (isset($fieldReadBlackListDetails['isReadBlackList']) && $fieldReadBlackListDetails['isReadBlackList']) { + throw new Exception\ForbiddenFieldAccessException($column); + }else if(isset($fieldReadBlackListDetails['statuses']) && !empty ($fieldReadBlackListDetails['statuses'])){ + $blackListStatuses = array_merge($blackListStatuses,array_values($fieldReadBlackListDetails['statuses'])); + } + } + $filters = $this->parseDotFilters($query, $filters); + + foreach ($filters as $column => $conditions) { if ($conditions instanceof Filter) { $column = $conditions->getIdentifier(); $conditions = $conditions->getValue(); @@ -1468,6 +1535,14 @@ protected function processFilter(Builder $query, array $filters = []) $this->doFilter($query, $column, $condition, $this->getTable()); } } + //Condition for blacklisted statuses + if(!empty($blackListStatuses)){ + $statusCondition = [ + 'nin' => array_unique($blackListStatuses) + ]; + $statusFieldName = SchemaService::getStatusFieldName($this->getTable()); + $this->doFilter($query, $statusFieldName, $statusCondition, $this->getTable()); + } } /** @@ -1570,7 +1645,7 @@ protected function processSort(Builder $query, array $columns) $field = SchemaService::getField($this->table, $orderBy, false, $this->acl === null); if ($orderBy !== '?' && !$field) { - throw new Exception\InvalidFieldException($column); + throw new Exception\InvalidFieldException($column, $this->table); } if ($field && $field->isAlias()) { @@ -1638,6 +1713,8 @@ protected function applyLegacyParams(Builder $query, array $params = []) } $query->whereIn($this->primaryKeyFieldName, $entriesIds); + //TODO add the following change to MySQL only as-is; must be transformed for other RDBMS + //$query->whereIn(new Expression('CAST(`'.$this->getTable().'`.`'.$this->primaryKeyFieldName.'` as CHAR)'), $entriesIds); } if (!ArrayUtils::has($params, 'q')) { @@ -1647,7 +1724,8 @@ protected function applyLegacyParams(Builder $query, array $params = []) $columns = SchemaService::getAllNonAliasCollectionFields($this->getTable()); $query->nestWhere(function (Builder $query) use ($columns, $search) { foreach ($columns as $column) { - if ($column->getType() === 'VARCHAR' || $column->getType()) { + //TODO check if still O.K. for MySQL + if (DataTypes::isStringType($column->getType()) || $column->getType()) { $query->whereLike($column->getName(), $search); } } @@ -1754,7 +1832,7 @@ public function loadOneToManyRelationships($entries, $columns, array $params = [ // $row->getId(); RowGateway perhaps? $relationalColumnId = $row[$relationalColumnName]; if (is_array($relationalColumnId) && !empty($relationalColumnId)) { - $relationalColumnId = $relationalColumnId[$tableGateway->primaryKeyFieldName]; + $relationalColumnId = $relationalColumnId[$primaryKey]; } if ($filterFields && !in_array('*', $filterFields)) { @@ -1891,7 +1969,8 @@ public function loadManyToOneRelationships($entries, $columns, array $params = [ foreach ($entries as &$parentRow) { if (array_key_exists($relationalColumnName, $parentRow)) { // @NOTE: Not always will be a integer - $foreign_id = (int)$parentRow[$relationalColumnName]; + // @NOTE: But what about UUIDS and slugs? + $foreign_id = (string)$parentRow[$relationalColumnName]; $parentRow[$relationalColumnName] = null; // "Did we retrieve the foreign row with this foreign ID in our recent query of the foreign table"? if (array_key_exists($foreign_id, $relatedEntries)) { @@ -2029,7 +2108,7 @@ public function validateFields(array $fields) foreach ($selectedFields as $field) { if (!$collection->hasField($field)) { - throw new Exception\InvalidFieldException($field); + throw new Exception\InvalidFieldException($field, $collection->getName()); } } } diff --git a/src/core/Directus/Filesystem/Thumbnailer.php b/src/core/Directus/Filesystem/Thumbnailer.php index 0b7446c76e..a2bb6179e6 100644 --- a/src/core/Directus/Filesystem/Thumbnailer.php +++ b/src/core/Directus/Filesystem/Thumbnailer.php @@ -45,7 +45,7 @@ class Thumbnailer { * @param Filesystem $main * @param Filesystem $thumb * @param array $config - * @param string $path in the form '_/100/100/crop/good/some-image.jpg' + * @param string $path in the form '_/100/100/crop/good/path/to/some-image.jpg' * * @throws Exception */ @@ -217,84 +217,50 @@ public function crop() */ public function extractThumbnailParams($thumbnailUrlPath) { - try { - if ($this->thumbnailParams) { - return $this->thumbnailParams; - } - - $urlSegments = explode('/', $thumbnailUrlPath); - - // pull the env out of the segments - array_shift($urlSegments); - - if (! $urlSegments) { - throw new Exception('Invalid thumbnailUrlPath.'); - } - - // pop off the filename - $fileName = ArrayUtils::pop($urlSegments); - - // make sure filename is valid - $ext = pathinfo($fileName, PATHINFO_EXTENSION); - $name = pathinfo($fileName, PATHINFO_FILENAME); - if (! $this->isSupportedFileExtension($ext)) { - throw new Exception('Invalid file extension.'); - } - - $thumbnailParams = [ - 'fileName' => filename_put_ext($name, $ext), - 'fileExt' => $ext - ]; - - foreach ($urlSegments as $segment) { - - if (! $segment) continue; - - $hasWidth = ArrayUtils::get($thumbnailParams, 'width'); - $hasHeight = ArrayUtils::get($thumbnailParams, 'height'); - // extract width and height - if ((!$hasWidth || !$hasHeight) && is_numeric($segment)) { - if (!$hasWidth) { - ArrayUtils::set($thumbnailParams, 'width', $segment); - } else if (!$hasHeight) { - ArrayUtils::set($thumbnailParams, 'height', $segment); - } - } - - // extract action and quality - else { - if (!ArrayUtils::get($thumbnailParams, 'action')) { - ArrayUtils::set($thumbnailParams, 'action', $segment); - } else if (!ArrayUtils::get($thumbnailParams, 'quality')) { - ArrayUtils::set($thumbnailParams, 'quality', $segment); - } - } - } + // cache + if ($this->thumbnailParams) { + return $this->thumbnailParams; + } - // validate - if (! ArrayUtils::contains($thumbnailParams, [ - 'width', - 'height' - ])) { - throw new Exception('No height or width provided.'); - } + // get URL parts + // https://docs.directus.io/guides/thumbnailer.html#url-syntax + $urlSegments = explode('/', $thumbnailUrlPath); + if (count($urlSegments) < 6) { + throw new Exception('Invalid URL syntax.'); + } - // set default action, if needed - if (! ArrayUtils::exists($thumbnailParams, 'action')) { - ArrayUtils::set($thumbnailParams, 'action', null); - } + // pull the env out of the segments + array_shift($urlSegments); - // set quality to null, if needed - if (! ArrayUtils::exists($thumbnailParams, 'quality')) { - ArrayUtils::set($thumbnailParams, 'quality', null); - } + // set thumbnail parameters + $thumbnailParams = [ + 'action' => filter_var($urlSegments[2], FILTER_SANITIZE_STRING), + 'height' => filter_var($urlSegments[1], FILTER_SANITIZE_NUMBER_INT), + 'quality' => filter_var($urlSegments[3], FILTER_SANITIZE_STRING), + 'width' => filter_var($urlSegments[0], FILTER_SANITIZE_NUMBER_INT), + ]; - return $thumbnailParams; + // validate parameters + if (! ArrayUtils::contains($thumbnailParams, [ + 'width', + 'height' + ])) { + throw new Exception('No height or width provided.'); } - catch (Exception $e) { - throw $e; + // make sure filename is valid + $filename = implode('/', array_slice($urlSegments, 4)); + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $name = pathinfo($filename, PATHINFO_FILENAME); + if (! $this->isSupportedFileExtension($ext)) { + throw new Exception('Invalid file extension.'); } + + // Set thumbnail filename parameters + $thumbnailParams['fileName'] = $filename; + $thumbnailParams['fileExt'] = $ext; + + return $thumbnailParams; } /** diff --git a/src/core/Directus/Permissions/Acl.php b/src/core/Directus/Permissions/Acl.php index e6c712d6ae..7e7b54d051 100644 --- a/src/core/Directus/Permissions/Acl.php +++ b/src/core/Directus/Permissions/Acl.php @@ -1240,16 +1240,33 @@ public function enforceWriteField($collection, $fields, $status = null) * * @return boolean */ - public function allowTo($action, $level, $collection, $status = null) + public function allowTo($action, $level, $collection, $status = null) { if ($this->isAdmin()) { return true; } $permission = $this->getPermission($collection, $status); - $permissionLevel = ArrayUtils::get($permission, $action); - return $this->can($permissionLevel, $level); + if (count($permission) === 0) { + $statuses = $this->getCollectionStatuses($collection); + + $allowed = false; + if($statuses){ + foreach ($statuses as $status) { + $permission = $this->getPermission($collection, $status); + $permissionLevel = ArrayUtils::get($permission, $action); + if ($this->can($permissionLevel, $level)) { + $allowed = true; + break; + } + } + } + return $allowed; + } else { + $permissionLevel = ArrayUtils::get($permission, $action); + return $this->can($permissionLevel, $level); + } } public function allowToOnce($action, $collection) @@ -1277,7 +1294,40 @@ public function allowToOnce($action, $collection) return $allowed; } - + + /** + * Gets the statuses on which field has been blacklisted + * + * @param string $collection + * @param mixed $status + * + * @return array + */ + public function getStatusesOnReadFieldBlacklist($collection, $field) + { + $blackListStatuses = []; + $collectionPermission = $this->getCollectionPermissions($collection); + $statuses = $this->getCollectionStatuses($collection); + if($statuses){ + foreach($statuses as $status){ + $readFieldBlackList = isset($collectionPermission[$status]['read_field_blacklist']) ? $collectionPermission[$status]['read_field_blacklist'] : []; + if($readFieldBlackList && in_array($field, $readFieldBlackList)){ + $blackListStatuses['statuses'][] = $status; + } + } + //Set flag for field which is blacklist for all statuses + if(isset($blackListStatuses['statuses']) && count($blackListStatuses['statuses']) == count($statuses)){ + $blackListStatuses['isReadBlackList'] = true; + } + }else{ + $readFieldBlackList = isset($collectionPermission['read_field_blacklist']) ? $collectionPermission['read_field_blacklist'] : []; + if($readFieldBlackList && in_array($field, $readFieldBlackList)){ + $blackListStatuses['isReadBlackList'] = true; + } + } + return $blackListStatuses; + } + /** * Returns a list of status the given collection has permission to read * diff --git a/src/core/Directus/Services/MailService.php b/src/core/Directus/Services/MailService.php index 9db0f9d2ba..067871bb0a 100644 --- a/src/core/Directus/Services/MailService.php +++ b/src/core/Directus/Services/MailService.php @@ -11,6 +11,7 @@ use Directus\Util\ArrayUtils; use Directus\Validator\Validator; use Zend\Db\Sql\Predicate\In; +use function Directus\get_project_config; class MailService extends AbstractService { @@ -24,16 +25,19 @@ public function send(array $data) 'to' => 'required' ]); + $acl = $this->container->get('acl'); + $subject = ArrayUtils::get($data, 'subject'); $toAddresses = $this->getToAddresses(ArrayUtils::get($data, 'to')); + $useDefaultEmail = isset($data['use_default_email']) && $acl->isAdmin() ? $data['use_default_email'] : false; send_mail_with_layout( - 'base.twig', + $data['type'] == 'plain' ? 'plain.twig' : 'base.twig', $data['body'], (array) ArrayUtils::get($data, 'data'), $data['type'] == 'plain' ? 'text/plain' : 'text/html', - function (Message $message) use ($data, $toAddresses, $subject) { - $message->setFrom($this->getFrom()); + function (Message $message) use ($data, $toAddresses, $subject, $useDefaultEmail) { + $message->setFrom($this->getFrom($useDefaultEmail)); $message->setTo($toAddresses); $message->setSubject($subject); } @@ -153,13 +157,21 @@ protected function parseAddresses(array $addresses) * * @return array */ - protected function getFrom() + + protected function getFrom($defaultEmail = false) { /** @var Acl $acl */ $acl = $this->container->get('acl'); - - return [ - $acl->getUserEmail() => $acl->getUserFullName() - ]; + if ($defaultEmail) { + $config = get_project_config(); + return [ + $config->get('mail.default.from') => $acl->getUserFullName() + ]; + } + else { + return [ + $acl->getUserEmail() => $acl->getUserFullName() + ]; + } } } diff --git a/src/core/Directus/Services/SettingsService.php b/src/core/Directus/Services/SettingsService.php index 571901998a..ecda701979 100644 --- a/src/core/Directus/Services/SettingsService.php +++ b/src/core/Directus/Services/SettingsService.php @@ -57,12 +57,12 @@ public function findAll(array $params = []) public function findFile($id,array $params = []) { - return (new ItemsService($this->container))->findByIds(SchemaManager::COLLECTION_FILES, $id,$params); + return $this->itemsService->findByIds(SchemaManager::COLLECTION_FILES, $id,$params); } public function findAllFields(array $params = []) { - return (new ItemsService($this->container))->findAll(SchemaManager::COLLECTION_FIELDS, array_merge($params, [ + return $this->itemsService->findAll(SchemaManager::COLLECTION_FIELDS, array_merge($params, [ 'filter' => [ 'collection' => $this->collection ] diff --git a/src/core/Directus/Services/TablesService.php b/src/core/Directus/Services/TablesService.php index cd3af0d6eb..4df38f10b5 100644 --- a/src/core/Directus/Services/TablesService.php +++ b/src/core/Directus/Services/TablesService.php @@ -154,9 +154,7 @@ public function findByIds($name, array $params = []) $collectionNames = StringUtils::csv((string) $name); $result['data'] = $this->mergeMissingSchemaCollections($collectionNames, $result['data']); } catch (ItemNotFoundException $e) { - $data = $this->mergeSchemaCollection($name, []); - - $result = $tableGateway->wrapData($data, true, ArrayUtils::get($params, 'meta')); + throw $e; } if ($result['data'] === null) { @@ -988,7 +986,10 @@ protected function dropColumnSchema($collectionName, $fieldName) ] ]); - return $schemaFactory->buildTable($table) ? true : false; + //BUGFIX: Do nothing if there's nothing to do + $result = !$table ? true : $schemaFactory->buildTable($table); + + return $result ? true : false; } /** @@ -1158,7 +1159,6 @@ protected function hasFieldAttributeWith(array $fields, $attribute, $value, $max return $result; } - /** * @param string $name * @param array $data @@ -1177,11 +1177,11 @@ protected function createTableSchema($name, array $data) /** @var Emitter $hookEmitter */ $hookEmitter = $this->container->get('hook_emitter'); $hookEmitter->run('collection.create:before', $name); - - $result = $schemaFactory->buildTable($table); + $charset = $this->container->get('config')->get('database.charset'); + $result = $schemaFactory->buildTable($table,$charset); return $result ? true : false; - } + } /** * @param Collection $collection @@ -1235,18 +1235,15 @@ protected function updateTableSchema(Collection $collection, array $data) } } - //BUGFIX: Do nothing if there's nothing to do - if (empty($toAdd) && empty($toChange) && empty($toDrop)) { - return true; - } - $table = $schemaFactory->alterTable($name, [ 'add' => $toAdd, 'change' => $toChange, 'drop' => $toDrop - ]); + ]); + + //BUGFIX: Do nothing if there's nothing to do + $result = !$table ? true : $schemaFactory->buildTable($table); - $result = $schemaFactory->buildTable($table); $this->updateColumnsRelation($name, array_merge($toAdd, $toChange)); $hookEmitter->run('collection.update', [$name, $data]); @@ -1690,7 +1687,7 @@ protected function getAllFieldsParams(array $params) foreach ($sort as $field) { $field = (string)$field; if (!$collection->hasField($field)) { - throw new InvalidFieldException($field); + throw new InvalidFieldException($field, $collection->getName()); } } } @@ -1705,4 +1702,11 @@ protected function getAllFieldsParams(array $params) return $newParams; } + + public function getFieldObject($collection,$field) + { + $collectionObject = $this->getSchemaManager()->getCollection($collection); + $fieldObject = $collectionObject->getField($field); + return $fieldObject; + } } diff --git a/src/core/Directus/Util/Installation/InstallerUtils.php b/src/core/Directus/Util/Installation/InstallerUtils.php index 55056b8041..d6197ac01c 100644 --- a/src/core/Directus/Util/Installation/InstallerUtils.php +++ b/src/core/Directus/Util/Installation/InstallerUtils.php @@ -683,62 +683,10 @@ private static function getDefaultSettings($data) 'key' => 'project_name', 'value' => isset($data['project_name']) ? $data['project_name'] : 'Directus' ], - [ - 'key' => 'project_url', - 'value' => '' - ], [ 'key' => 'app_url', 'value' => isset($data['app_url']) ? $data['app_url'] : '' ], - [ - 'key' => 'logo', - 'value' => '' - ], - [ - 'key' => 'color', - 'value' => 'light-blue-600' - ], - [ - 'key' => 'default_limit', - 'value' => '200' - ], - [ - 'key' => 'sort_null_last', - 'value' => 1 - ], - [ - 'key' => 'auto_sign_out', - 'value' => '60' - ], - [ - 'key' => 'youtube_api_key', - 'value' => '' - ], - [ - 'key' => 'trusted_proxies', - 'value' => '' - ], - [ - 'key' => 'thumbnail_dimensions', - 'value' => '200x200' - ], - [ - 'key' => 'thumbnail_quality_tags', - 'value' => '{"poor": 25, "good": 50, "better": 75, "best": 100}' - ], - [ - 'key' => 'thumbnail_actions', - 'value' => '{"contain":{"options":{"resizeCanvas":false,"position":"center","resizeRelative":false,"canvasBackground":"ccc"}},"crop":{"options":{"position":"center"}}}' - ], - [ - 'key' => 'thumbnail_cache_ttl', - 'value' => '86400' - ], - [ - 'key' => 'thumbnail_not_found_location', - 'value' => '' - ], ]; } @@ -973,7 +921,7 @@ private static function createConfigData(array $data) ], 'headers' => [], 'exposed_headers' => [], - 'max_age' => null, + 'max_age' => 600, 'credentials' => false, ], 'rate_limit' => [ diff --git a/src/core/Directus/Util/MimeTypeUtils.php b/src/core/Directus/Util/MimeTypeUtils.php index a65e72cfef..4b7027e56e 100644 --- a/src/core/Directus/Util/MimeTypeUtils.php +++ b/src/core/Directus/Util/MimeTypeUtils.php @@ -3018,7 +3018,7 @@ class MimeTypeUtils */ public static function getFromExtension($extension) { - return static::get(self::$reverseMap, $extension, 'application/octet-stream'); + return static::get(self::$reverseMap, strtolower($extension), 'application/octet-stream'); } /** @@ -3043,7 +3043,6 @@ public static function getFromMimeType($type) public static function getFromFilename($filename) { $extension = pathinfo($filename, PATHINFO_EXTENSION); - return self::getFromExtension($extension); } diff --git a/src/core/Directus/Util/StringUtils.php b/src/core/Directus/Util/StringUtils.php index 9fea33259f..0ea7bed5ee 100644 --- a/src/core/Directus/Util/StringUtils.php +++ b/src/core/Directus/Util/StringUtils.php @@ -233,6 +233,12 @@ public static function replacePlaceholder($string, $data = [], $placeHolderForma } } + /** + * If any variable of the given string have null value as a replacement then the + * result will be 'null'(string). So we need to replace it with blank string. + */ + $string = str_replace("'null'", "''", $string); + // convert all remaining optionals placeholder from {{optional(key)}} to // 'key' => '' $pattern = '#^(.*)({{optional\((.*)\)}})(.*\n)?#im'; $string = preg_replace_callback($pattern, function ($matches) use ($keyName) { diff --git a/src/endpoints/Fields.php b/src/endpoints/Fields.php index 292e743871..d05ee406c7 100644 --- a/src/endpoints/Fields.php +++ b/src/endpoints/Fields.php @@ -11,8 +11,10 @@ use Directus\Exception\ErrorException; use Directus\Exception\UnauthorizedException; use Directus\Services\TablesService; +use Directus\Services\PermissionsService; use Directus\Util\ArrayUtils; use Directus\Util\StringUtils; +use Directus\Database\Schema\DataTypes; class Fields extends Route { @@ -167,14 +169,31 @@ public function all(Request $request, Response $response) */ public function delete(Request $request, Response $response) { + $service = new TablesService($this->container); + $field = $service->getFieldObject($request->getAttribute('collection'),$request->getAttribute('field')); + $service->deleteField( $request->getAttribute('collection'), $request->getAttribute('field'), $request->getQueryParams() ); + /** + * If the field is status then remove the status related permission. + */ + + if (DataTypes::isStatusType($field->getType())) { + $permissionService = new PermissionsService($this->container); + $filter['filter']['collection'] = $request->getAttribute('collection'); + $filter['filter']['status']['neq'] = ""; + $collectionsPermission = $permissionService->findAll($filter); + $permissionId = array_column($collectionsPermission['data'], 'id'); + $permissionService->batchDeleteWithIds($permissionId); + + } + return $this->responseWithData($request, $response, []); } diff --git a/src/endpoints/Settings.php b/src/endpoints/Settings.php index 85feadd118..4498001a32 100644 --- a/src/endpoints/Settings.php +++ b/src/endpoints/Settings.php @@ -79,25 +79,28 @@ public function all(Request $request, Response $response) ); /** - * Generate the response object based on interface - * + * Generate the response object based on interface/type + * */ - foreach($fieldData['data'] as $key => $value){ - switch ($value['interface']) { - case 'file': - $result = array_search($value['field'], array_column($responseData['data'], 'key')); - if($result){ - if (!empty($responseData['data'][$result]['value'])) { - $fileInstence = $service->findFile($responseData['data'][$result]['value']); - $responseData['data'][$result]['value'] = !empty($fileInstence['data']) ? $fileInstence['data'] : null; - } else { - $responseData['data'][$result]['value'] = null; + foreach($fieldData['data'] as $fieldDefinition){ + // find position of field in $response['data'] + $index = array_search($fieldDefinition['field'], array_column($responseData['data'], 'key')); + if (false !== $index) { + + switch ($fieldDefinition['type']) { + case 'file': + if (!empty($responseData['data'][$index]['value'])) { + $fileInstance = $service->findFile($responseData['data'][$index]['value']); + $responseData['data'][$index]['value'] = null; + + if (!empty($fileInstance['data'])) { + $responseData['data'][$index]['value'] = $fileInstance['data']; + } } - } - break; - case 'tags': - $inputData['value'] = !empty($responseData['data'][$result]['value']) ? explode($responseData['data'][$result]['value']) : null; - break; + break; + default: + break; + } } } @@ -137,36 +140,6 @@ public function read(Request $request, Response $response) return $this->responseWithData($request, $response, $responseData); } - - /** - * @param Request $request - * @param Response $response - * - * @return Response - */ - public function getInterfaceBasedInput($request,$setting) - { - $service = new SettingsService($this->container); - $fieldData = $service->findAllFields( - $request->getQueryParams() - ); - - $inputData = $request->getParsedBody(); - foreach($fieldData['data'] as $key => $value){ - if($value['field'] == $setting){ - switch ($value['interface']) { - case 'file': - $inputData['value'] = isset($inputData['value']['id']) ? $inputData['value']['id'] : $inputData['value']; - break; - case 'tags': - $inputData['value'] = is_array($inputData['value']) ? implode(",",$inputData['value']) : $inputData['value']; - break; - } - } - } - return $inputData; - } - /** * @param Request $request * @param Response $response @@ -183,13 +156,21 @@ public function getInterfaceBasedInput($request,$setting) $inputData = $request->getParsedBody(); foreach($fieldData['data'] as $key => $value){ if($value['field'] == $setting){ - switch ($value['interface']) { - case 'file': - $inputData['value'] = isset($inputData['value']['id']) ? $inputData['value']['id'] : $inputData['value']; - break; - case 'tags': - $inputData['value'] = is_array($inputData['value']) ? implode(",",$inputData['value']) : $inputData['value']; - break; + if($inputData['value'] != null){ + switch ($value['type']) { + case 'file': + $inputData['value'] = isset($inputData['value']['id']) ? $inputData['value']['id'] : $inputData['value']; + break; + case 'array': + $inputData['value'] = is_array($inputData['value']) ? implode(",",$inputData['value']) : $inputData['value']; + break; + case 'json': + $inputData['value'] = json_encode($inputData['value']); + break; + } + }else{ + // To convert blank string in null + $inputData['value'] = null; } } } @@ -204,8 +185,6 @@ public function getInterfaceBasedInput($request,$setting) */ public function update(Request $request, Response $response) { - $this->validateRequestPayload($request); - $payload = $request->getParsedBody(); $id = $request->getAttribute('id'); @@ -240,6 +219,7 @@ public function update(Request $request, Response $response) * Get the interface based input * */ + $inputData = $this->getInterfaceBasedInput($request,$serviceData['data']['key']); $responseData = $service->update( $request->getAttribute('id'), diff --git a/src/helpers/extensions.php b/src/helpers/extensions.php index 03a20283a2..7099eef010 100644 --- a/src/helpers/extensions.php +++ b/src/helpers/extensions.php @@ -36,7 +36,10 @@ function get_custom_x($type, $path, $onlyDirectories = false) $pathInfo = pathinfo($relativePath); $dirname = $pathInfo['dirname']; $extensionName = $pathInfo['filename']; - $isDirectory = $dirname !== '/'; + /** + * For windows system the path is '\' instead of '/'. So we need to check for both slashes. + */ + $isDirectory = $dirname !== '/' && $dirname !== '\\'; // TODO: Need to improve logic if (in_array($dirname, $ignoredDirectories)) { diff --git a/src/helpers/mail.php b/src/helpers/mail.php index 7df331186b..8fe2dc9e94 100644 --- a/src/helpers/mail.php +++ b/src/helpers/mail.php @@ -94,7 +94,7 @@ function get_safe_tags() { return array_map(function ($tagName) { return '<' . $tagName . '>'; - }, ['b', 'button', 'a', 'i', 'h1']); + }, ['b', 'i', 'a', 'p', 'br', 'hr', 'button', 'h1', 'h2', 'h3', 'h4', 'h5', 'table', 'thead', 'tbody', 'tfoot', 'th', 'tr', 'td']); } } diff --git a/src/mail/plain.twig b/src/mail/plain.twig new file mode 100644 index 0000000000..f427546b32 --- /dev/null +++ b/src/mail/plain.twig @@ -0,0 +1,4 @@ +{% block content %}{{ body|raw }}{% endblock %} + + +This email was sent by Directus – {{settings.project_name }} \ No newline at end of file diff --git a/src/web.php b/src/web.php index 70dcd96080..96065d5f14 100644 --- a/src/web.php +++ b/src/web.php @@ -196,7 +196,9 @@ foreach ($endpointsList as $name => $endpoints) { \Directus\create_group_route_from_array($this, $name, $endpoints); } - })->add($middleware['table_gateway']); + }) + ->add($middleware['auth']) + ->add($middleware['table_gateway']); $this->group('/pages', function () { $endpointsList = \Directus\get_custom_endpoints('public/extensions/core/pages', true);