added mind map
This commit is contained in:
parent
ed5c0a4223
commit
f55873a425
|
@ -29,14 +29,29 @@ export const INITIAL_MIND = {
|
|||
|
||||
// 模擬打 API
|
||||
// Simulate an API call to search based on the query
|
||||
export async function mockSearchApi(query) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve([
|
||||
{ text: `${query} 建議1`, link: `https://example.com/${query}1` },
|
||||
{ text: `${query} 建議2`, link: `https://example.com/${query}2` },
|
||||
{ text: `${query} 建議3`, link: `https://example.com/${query}3` },
|
||||
])
|
||||
}, 500)
|
||||
})
|
||||
export async function mockSearchApi(query, tableUID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", '/admin/universal_tables/get_entries?uid=' + tableUID + "&q=" + query + "&links=true");
|
||||
xhr.setRequestHeader("Accept", "application/json");
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
const data = JSON.parse(xhr.responseText);
|
||||
resolve(data); // success
|
||||
} catch (e) {
|
||||
reject(new Error("Invalid JSON response"));
|
||||
}
|
||||
} else {
|
||||
reject(new Error(`Request failed with status ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
reject(new Error("Network error"));
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ export function initJsmind(mind, options, isEditable) {
|
|||
// 掛載附加模組(遠程搜尋 & 工具列)
|
||||
// Attach additional modules (Remote search & Toolbar)
|
||||
if (isEditable) {
|
||||
new JsmindSearch(jm, mockSearchApi)
|
||||
new JsmindToolbar(jm)
|
||||
new JsmindSearch(jm, mockSearchApi, options.tableUID);
|
||||
new JsmindToolbar(jm, options)
|
||||
}
|
||||
|
||||
return jm
|
||||
|
|
|
@ -14,13 +14,14 @@ export class JsmindSearch {
|
|||
* Constructor for search
|
||||
* @param {Object} jm - jsMind 實例 (jsMind instance)
|
||||
* @param {Function} searchAPI - 遠程搜尋 API 函式 (Remote search API function)
|
||||
* @param {string} tableUID
|
||||
*/
|
||||
constructor(jm, searchAPI) {
|
||||
constructor(jm, searchAPI, tableUID) {
|
||||
this.jm = jm
|
||||
this.searchAPI = searchAPI
|
||||
this.container = document.getElementById(jm.options.container)
|
||||
this.suggestionBox = null
|
||||
|
||||
this.tableUID = tableUID
|
||||
this.init()
|
||||
}
|
||||
|
||||
|
@ -77,8 +78,9 @@ export class JsmindSearch {
|
|||
async onInput(node, e) {
|
||||
const query = e.target.value.trim()
|
||||
if (!query) return
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
try {
|
||||
const results = await this.searchAPI(query)
|
||||
const results = await this.searchAPI(query, this.tableUID)
|
||||
this.showSuggestion(node, e.target, results)
|
||||
} catch (error) {
|
||||
// Search API error handling
|
||||
|
|
|
@ -13,8 +13,9 @@ export class JsmindToolbar {
|
|||
* 建構工具列
|
||||
* Constructor for toolbar
|
||||
* @param {Object} jm - jsMind 實例 (jsMind instance)
|
||||
* @param {Object} options - jsMind 實例 (options)
|
||||
*/
|
||||
constructor(jm) {
|
||||
constructor(jm, options) {
|
||||
this.jm = jm
|
||||
this.container = document.getElementById(jm.options.container)
|
||||
this.toolbarNodeId = null
|
||||
|
@ -22,7 +23,7 @@ export class JsmindToolbar {
|
|||
this.bgColorPalette = null
|
||||
this.strokeColorPalette = null
|
||||
this.textColorPalette = null
|
||||
|
||||
this.options = options
|
||||
this.init()
|
||||
}
|
||||
|
||||
|
@ -78,21 +79,21 @@ export class JsmindToolbar {
|
|||
// 建立工具列按鈕
|
||||
// Create toolbar buttons
|
||||
const buttons = [
|
||||
{ id: 'toolbar-add-child-btn', text: '新增', onClick: this.handleAddChild.bind(this) },
|
||||
{ id: 'toolbar-delete-btn', text: '刪除', onClick: this.handleDelete.bind(this) },
|
||||
{ id: 'toolbar-add-child-btn', text: this.options.text.addNode, onClick: this.handleAddChild.bind(this) },
|
||||
{ id: 'toolbar-delete-btn', text: this.options.text.deleteNode, onClick: this.handleDelete.bind(this) },
|
||||
{
|
||||
id: 'toolbar-stroke-color-btn',
|
||||
text: '線條顏色',
|
||||
text: this.options.text.strokeColor,
|
||||
onClick: this.handleStrokeColor.bind(this),
|
||||
},
|
||||
{
|
||||
id: 'toolbar-bg-color-btn',
|
||||
text: '背景顏色',
|
||||
text: this.options.text.bgColor,
|
||||
onClick: this.handleBgColor.bind(this),
|
||||
},
|
||||
{
|
||||
id: 'toolbar-text-color-btn',
|
||||
text: '文字顏色',
|
||||
text: this.options.text.textColor,
|
||||
onClick: this.handleTextColor.bind(this),
|
||||
},
|
||||
]
|
||||
|
|
|
@ -9,4 +9,20 @@ class Admin::MindMapsController < OrbitAdminController
|
|||
@mind_map = table.mind_map
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
mind_map = MindMap.find(params[:id])
|
||||
mind_params = mind_map_params
|
||||
mind_params[:mind_map_data] = JSON.parse(mind_params[:mind_map_data])
|
||||
mind_map.update_attributes(mind_map_params)
|
||||
mind_map.save
|
||||
redirect_to admin_universal_tables_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mind_map_params
|
||||
params.require(:mind_map).permit!
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -53,11 +53,20 @@ class Admin::UniversalTablesController < OrbitAdminController
|
|||
data = []
|
||||
if !table.nil?
|
||||
enteries = search_data(table, 50)
|
||||
ma = ModuleApp.find_by_key("universal_table")
|
||||
enteries.each do |entry|
|
||||
data << {
|
||||
"id" => entry.id.to_s,
|
||||
"text" => entry.column_entries.first.text
|
||||
}
|
||||
if params["links"].present?
|
||||
data << {
|
||||
"id" => entry.id.to_s,
|
||||
"text" => entry.column_entries.first.text,
|
||||
"link" => OrbitHelper.cal_url_to_show(ma,entry)
|
||||
}
|
||||
else
|
||||
data << {
|
||||
"id" => entry.id.to_s,
|
||||
"text" => entry.column_entries.first.text
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
render :json => data.to_json
|
||||
|
|
|
@ -351,4 +351,8 @@ class UniversalTablesController < ApplicationController
|
|||
render :file => "#{Rails.root}/app/views/errors/404.html", :layout => false, :status => :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def mind_map
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,8 @@ class MindMap
|
|||
include Slug
|
||||
|
||||
field :title, as: :slug_title, localize: true
|
||||
field :mind_map_data, type: Array, default: []
|
||||
|
||||
belongs_to :u_table
|
||||
has_many :mind_map_nodes, :dependent => :destroy
|
||||
# has_many :mind_map_nodes, :dependent => :destroy
|
||||
end
|
||||
|
|
|
@ -31,9 +31,15 @@
|
|||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button id="toggle_editable">Disable Editing</button>
|
||||
<button id="save_mind_map">Save Mind Map</button>
|
||||
<button id="toggle_editable"><%= t("universal_table.disable_editing") %></button>
|
||||
<button id="save_mind_map"><%= t("universal_table.save_mind_map") %></button>
|
||||
</div>
|
||||
<div id="jsmind_container"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="utable-content">
|
||||
<div class="form-actions">
|
||||
<%= f.hidden_field :mind_map_data, id: "mind_map_data_field", value: "" %>
|
||||
<input class="btn btn-primary pull-right" name="commit" id="save_mind_map" type="submit" value="<%= t("save") %>">
|
||||
</div>
|
||||
</fieldset>
|
|
@ -2,7 +2,7 @@
|
|||
<%= stylesheet_link_tag "universal_table/universal-table" %>
|
||||
<%= stylesheet_link_tag "mind_map/mindmap" %>
|
||||
<% end %>
|
||||
<%= form_for @mind_map, url: admin_mind_map_path(@mind_map), html: {class: "form-horizontal main-forms"} do |f| %>
|
||||
<%= form_for @mind_map, url: admin_mind_map_path(@mind_map.id), html: {class: "form-horizontal main-forms", id: "mind_map_form"} do |f| %>
|
||||
<%= render :partial => "form", locals: {f: f} %>
|
||||
<% end %>
|
||||
<script type="module">
|
||||
|
@ -21,7 +21,15 @@
|
|||
|
||||
// 心智圖初始數據
|
||||
// Initial mind map data
|
||||
<% if @mind_map.mind_map_data.empty? %>
|
||||
let mind = INITIAL_MIND
|
||||
<% else %>
|
||||
let mind = {
|
||||
meta: {},
|
||||
format: 'node_array',
|
||||
data: <%= raw @mind_map.mind_map_data.to_json %>
|
||||
}
|
||||
<% end %>
|
||||
|
||||
// 心智圖自訂選項(可參考 jsmind 官方文檔)
|
||||
// Custom options for the mind map (refer to the jsmind official documentation)
|
||||
|
@ -30,6 +38,14 @@
|
|||
editable: isEditable,
|
||||
theme: 'primary',
|
||||
mode: 'full',
|
||||
tableUID: '<%= @mind_map.u_table.uid %>',
|
||||
text: {
|
||||
addNode: "<%= t("universal_table.add_node") %>",
|
||||
deleteNode: "<%= t("universal_table.delete_node") %>",
|
||||
strokeColor: "<%= t("universal_table.stroke_color") %>",
|
||||
bgColor: "<%= t("universal_table.bg_color") %>",
|
||||
textColor: "<%= t("universal_table.text_color") %>"
|
||||
},
|
||||
view: {
|
||||
engine: 'svg',
|
||||
draggable: true,
|
||||
|
@ -53,8 +69,8 @@
|
|||
document.getElementById('save_mind_map').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
let data = getJsmindData(jm)
|
||||
console.log(data)
|
||||
let data = getJsmindData(jm);
|
||||
console.log(data);
|
||||
})
|
||||
|
||||
// 調整可編輯狀態
|
||||
|
@ -62,11 +78,19 @@
|
|||
document.getElementById('toggle_editable').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
isEditable = !isEditable
|
||||
e.target.innerHTML = isEditable ? 'Disable Editing' : 'Enable Editing'
|
||||
isEditable = !isEditable;
|
||||
e.target.innerHTML = isEditable ? '<%= t("universal_table.disable_editing") %>' : '<%= t("universal_table.enable_editing") %>';
|
||||
|
||||
mind = getJsmindData(jm)
|
||||
jm = initJsmind(mind, options, isEditable)
|
||||
mind = getJsmindData(jm);
|
||||
jm = initJsmind(mind, options, isEditable);
|
||||
return false;
|
||||
})
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const form = document.getElementById("mind_map_form");
|
||||
const hiddenField = document.getElementById("mind_map_data_field");
|
||||
form.addEventListener("submit", function (e) {
|
||||
const mindMapData = getJsmindData(jm);
|
||||
hiddenField.value = JSON.stringify(mindMapData.data);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -21,4 +21,12 @@ en:
|
|||
drag_file_to_here: Drag file to here
|
||||
show_lang: Language
|
||||
downloaded_times: Downloaded Times
|
||||
mind_map: Mind Map
|
||||
mind_map: Mind Map
|
||||
add_node: Add Node
|
||||
delete_node: Delete Node
|
||||
stroke_color: Line Color
|
||||
bg_color: Background Color
|
||||
text_color: Text Color
|
||||
disable_editing: Disable editing
|
||||
enable_editing: Enable editing
|
||||
save_mind_map: Save mind map
|
|
@ -21,4 +21,12 @@ zh_tw:
|
|||
drag_file_to_here: 拖移檔案到此
|
||||
show_lang: 呈現語系
|
||||
downloaded_times: 下載次數
|
||||
mind_map: Mind Map
|
||||
mind_map: Mind Map
|
||||
add_node: 新增
|
||||
delete_node: 刪除
|
||||
stroke_color: 線條顏色
|
||||
bg_color: 背景顏色
|
||||
text_color: 文字顏色
|
||||
disable_editing: Disable editing
|
||||
enable_editing: Enable editing
|
||||
save_mind_map: Save mind map
|
Loading…
Reference in New Issue