Upload app.R
Browse files
app.R
CHANGED
|
@@ -16,15 +16,6 @@ orderInputPanel <- function() {
|
|
| 16 |
)
|
| 17 |
}
|
| 18 |
|
| 19 |
-
textInputPanel <- function() {
|
| 20 |
-
conditionalPanel(
|
| 21 |
-
condition = "output.showTextInput",
|
| 22 |
-
textInput("related_captions_input", "Enter related captions (comma separated):"),
|
| 23 |
-
actionButton("confirm_text", "Confirm Order"),
|
| 24 |
-
actionButton("cancel_text", "Cancel")
|
| 25 |
-
)
|
| 26 |
-
}
|
| 27 |
-
|
| 28 |
# キャプションの並び替え関数
|
| 29 |
sort_captions_by_search <- function(data, search_term) {
|
| 30 |
if (is.null(search_term) || search_term == "") {
|
|
@@ -64,14 +55,16 @@ ui <- fluidPage(
|
|
| 64 |
tags$script(HTML("
|
| 65 |
function handleCaptionClick(caption, source) {
|
| 66 |
var operationModeElement = document.getElementById('operation_mode_UI');
|
| 67 |
-
if (
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
|
|
|
|
|
|
| 73 |
} else if (operationModeElement && operationModeElement.innerText === 'Database Making') {
|
| 74 |
-
|
| 75 |
} else {
|
| 76 |
copyToClipboard(caption);
|
| 77 |
}
|
|
@@ -106,7 +99,7 @@ ui <- fluidPage(
|
|
| 106 |
tags$br(),
|
| 107 |
|
| 108 |
# Direct Removerモード
|
| 109 |
-
actionButton("direct_remover", "Direct Remover"),
|
| 110 |
conditionalPanel(
|
| 111 |
condition = "output.operation_mode_UI === 'direct remove'",
|
| 112 |
actionButton("exit_direct_remover", "Exit Direct Remover")
|
|
@@ -134,6 +127,8 @@ ui <- fluidPage(
|
|
| 134 |
actionButton("aggregate_single", "Aggregation Single"),
|
| 135 |
actionButton("aggregate_all", "Aggregation All")
|
| 136 |
),
|
|
|
|
|
|
|
| 137 |
|
| 138 |
conditionalPanel(
|
| 139 |
condition = "output.operation_mode_UI !== 'direct remove' && output.operation_mode_UI !== 'Database Making'",
|
|
@@ -156,10 +151,10 @@ ui <- fluidPage(
|
|
| 156 |
actionButton("move_caption", "Move Single"),
|
| 157 |
actionButton("move_caption_all", "Move All"),
|
| 158 |
tags$br(),
|
| 159 |
-
actionButton("remove_related_single", "Remove Related Single"),
|
| 160 |
-
actionButton("remove_related_all", "Remove Related All"),
|
| 161 |
orderInputPanel(),
|
| 162 |
-
textInputPanel(), # ここで関数を呼び出しています
|
| 163 |
tags$br(),
|
| 164 |
),
|
| 165 |
tags$br(),
|
|
@@ -182,10 +177,12 @@ ui <- fluidPage(
|
|
| 182 |
textInput("search_caption", "Search Caption:", ""),
|
| 183 |
actionButton("search_button", "Search"),
|
| 184 |
actionButton("clear_search", "Clear"),
|
|
|
|
|
|
|
| 185 |
fluidRow(
|
| 186 |
column(4, tableOutput("selected_image_captions")),
|
| 187 |
column(4, tableOutput("caption_frequency_table_with_links")),
|
| 188 |
-
column(4, tableOutput("
|
| 189 |
)
|
| 190 |
)
|
| 191 |
)
|
|
@@ -357,13 +354,15 @@ server <- function(input, output, session) {
|
|
| 357 |
# 選択されている画像のcaptionを別変数に保存
|
| 358 |
captions_for_selected_image <- updated_data$caption[updated_data$image_path == input$selected_image]
|
| 359 |
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
|
|
|
|
|
|
| 367 |
}
|
| 368 |
}
|
| 369 |
|
|
@@ -379,17 +378,19 @@ server <- function(input, output, session) {
|
|
| 379 |
observeEvent(input$aggregate_all, {
|
| 380 |
updated_data <- captions_data()
|
| 381 |
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
for (i in 1:nrow(relation_database())) {
|
| 387 |
-
parent <- relation_database()$parent_caption[i]
|
| 388 |
-
child <- relation_database()$child_caption[i]
|
| 389 |
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
}
|
| 394 |
}
|
| 395 |
}
|
|
@@ -403,6 +404,20 @@ server <- function(input, output, session) {
|
|
| 403 |
update_log("Captions aggregated for all images.")
|
| 404 |
})
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
# Relation Databaseをセーブ
|
| 407 |
output$save_relation_database <- downloadHandler(
|
| 408 |
filename = function() {
|
|
@@ -592,36 +607,6 @@ server <- function(input, output, session) {
|
|
| 592 |
update_log("MOVE CAPTION ALL MODE.")
|
| 593 |
})
|
| 594 |
|
| 595 |
-
observeEvent(input$remove_related_single, {
|
| 596 |
-
if (operation_mode() != "Normal") {
|
| 597 |
-
showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
|
| 598 |
-
return()
|
| 599 |
-
}
|
| 600 |
-
if (!is.null(captions_data())) {
|
| 601 |
-
selected_image_path <- input$selected_image
|
| 602 |
-
target_caption <- input$edit_caption
|
| 603 |
-
|
| 604 |
-
# target_captionが選択された画像に紐づいているか確認
|
| 605 |
-
if (any(captions_data()$image_path == selected_image_path & captions_data()$caption == target_caption)) {
|
| 606 |
-
operation_mode("remove_related_single")
|
| 607 |
-
showTextInput(TRUE)
|
| 608 |
-
update_log("RELATIVE REMOVE SINGLE MODE.")
|
| 609 |
-
} else {
|
| 610 |
-
showNotification("Error: Caption not found in the selected image.", type = "error")
|
| 611 |
-
}
|
| 612 |
-
}
|
| 613 |
-
})
|
| 614 |
-
|
| 615 |
-
observeEvent(input$remove_related_all, {
|
| 616 |
-
if (operation_mode() != "Normal") {
|
| 617 |
-
showNotification("Another operation is in progress. Please finish or cancel it first.", type = "error")
|
| 618 |
-
return()
|
| 619 |
-
}
|
| 620 |
-
operation_mode("remove_related_all")
|
| 621 |
-
showTextInput(TRUE)
|
| 622 |
-
update_log("RELATIVE REMOVE ALL MODE.")
|
| 623 |
-
})
|
| 624 |
-
|
| 625 |
observeEvent(input$confirm_order, {
|
| 626 |
switch(operation_mode(),
|
| 627 |
"add_single" = {
|
|
@@ -672,46 +657,6 @@ server <- function(input, output, session) {
|
|
| 672 |
showOrderInput(FALSE)
|
| 673 |
})
|
| 674 |
|
| 675 |
-
|
| 676 |
-
observeEvent(input$confirm_text, {
|
| 677 |
-
switch(operation_mode(),
|
| 678 |
-
"remove_related_single" = {
|
| 679 |
-
# Remove Related captions of Singleの処理
|
| 680 |
-
related_captions <- unlist(strsplit(input$related_captions_input, ","))
|
| 681 |
-
related_captions <- trimws(related_captions) # スペースを削除
|
| 682 |
-
representative_caption <- input$edit_caption
|
| 683 |
-
|
| 684 |
-
updated_data <- remove_related_captions_except_representative(captions_data(), related_captions, representative_caption, input$selected_image)
|
| 685 |
-
captions_data(updated_data)
|
| 686 |
-
update_log("Relative captions were removed from this image.")
|
| 687 |
-
},
|
| 688 |
-
"remove_related_all" = {
|
| 689 |
-
# Remove Related captions from All Imagesの処理
|
| 690 |
-
related_captions <- unlist(strsplit(input$related_captions_input, ","))
|
| 691 |
-
related_captions <- trimws(related_captions) # スペースを削除
|
| 692 |
-
representative_caption <- input$edit_caption
|
| 693 |
-
|
| 694 |
-
updated_data <- captions_data()
|
| 695 |
-
# representative_captionを持つすべての画像を検索
|
| 696 |
-
images_with_rep_caption <- unique(updated_data$image_path[updated_data$caption == representative_caption])
|
| 697 |
-
|
| 698 |
-
for (image_path in images_with_rep_caption) {
|
| 699 |
-
updated_data <- remove_related_captions_except_representative(updated_data, related_captions, representative_caption, image_path)
|
| 700 |
-
}
|
| 701 |
-
|
| 702 |
-
captions_data(updated_data)
|
| 703 |
-
update_log("Relative captions were removed from all images.")
|
| 704 |
-
}
|
| 705 |
-
)
|
| 706 |
-
|
| 707 |
-
# キャプションの頻度を更新
|
| 708 |
-
updated_caption_frequency <- get_caption_frequency(captions_data())
|
| 709 |
-
caption_frequency(updated_caption_frequency)
|
| 710 |
-
operation_mode("Normal")
|
| 711 |
-
showTextInput(FALSE)
|
| 712 |
-
})
|
| 713 |
-
|
| 714 |
-
|
| 715 |
observeEvent(input$cancel_order, {
|
| 716 |
operation_mode("Normal")
|
| 717 |
showOrderInput(FALSE)
|
|
@@ -902,9 +847,17 @@ server <- function(input, output, session) {
|
|
| 902 |
}
|
| 903 |
}, sanitize.text.function = function(x) x)
|
| 904 |
|
| 905 |
-
output$
|
| 906 |
-
relation_database()
|
| 907 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 908 |
}
|
| 909 |
|
| 910 |
# アプリを実行
|
|
|
|
| 16 |
)
|
| 17 |
}
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
# キャプションの並び替え関数
|
| 20 |
sort_captions_by_search <- function(data, search_term) {
|
| 21 |
if (is.null(search_term) || search_term == "") {
|
|
|
|
| 55 |
tags$script(HTML("
|
| 56 |
function handleCaptionClick(caption, source) {
|
| 57 |
var operationModeElement = document.getElementById('operation_mode_UI');
|
| 58 |
+
if (source === 'remove_RDB') {
|
| 59 |
+
Shiny.setInputValue('remove_relation_index', caption, {priority: 'event'});
|
| 60 |
+
} else if (operationModeElement && operationModeElement.innerText === 'direct remove') {
|
| 61 |
+
if (source === 'frequency') {
|
| 62 |
+
Shiny.setInputValue('clicked_caption_frequency', caption, {priority: 'event'});
|
| 63 |
+
} else {
|
| 64 |
+
Shiny.setInputValue('clicked_caption', caption, {priority: 'event'});
|
| 65 |
+
}
|
| 66 |
} else if (operationModeElement && operationModeElement.innerText === 'Database Making') {
|
| 67 |
+
Shiny.setInputValue('clicked_caption_RDB', caption, {priority: 'event'});
|
| 68 |
} else {
|
| 69 |
copyToClipboard(caption);
|
| 70 |
}
|
|
|
|
| 99 |
tags$br(),
|
| 100 |
|
| 101 |
# Direct Removerモード
|
| 102 |
+
actionButton("direct_remover", "Enter Direct Remover Mode"),
|
| 103 |
conditionalPanel(
|
| 104 |
condition = "output.operation_mode_UI === 'direct remove'",
|
| 105 |
actionButton("exit_direct_remover", "Exit Direct Remover")
|
|
|
|
| 127 |
actionButton("aggregate_single", "Aggregation Single"),
|
| 128 |
actionButton("aggregate_all", "Aggregation All")
|
| 129 |
),
|
| 130 |
+
tags$br(),
|
| 131 |
+
tags$br(),
|
| 132 |
|
| 133 |
conditionalPanel(
|
| 134 |
condition = "output.operation_mode_UI !== 'direct remove' && output.operation_mode_UI !== 'Database Making'",
|
|
|
|
| 151 |
actionButton("move_caption", "Move Single"),
|
| 152 |
actionButton("move_caption_all", "Move All"),
|
| 153 |
tags$br(),
|
| 154 |
+
# actionButton("remove_related_single", "Remove Related Single"),
|
| 155 |
+
# actionButton("remove_related_all", "Remove Related All"),
|
| 156 |
orderInputPanel(),
|
| 157 |
+
# textInputPanel(), # ここで関数を呼び出しています
|
| 158 |
tags$br(),
|
| 159 |
),
|
| 160 |
tags$br(),
|
|
|
|
| 177 |
textInput("search_caption", "Search Caption:", ""),
|
| 178 |
actionButton("search_button", "Search"),
|
| 179 |
actionButton("clear_search", "Clear"),
|
| 180 |
+
tags$br(),
|
| 181 |
+
tags$br(),
|
| 182 |
fluidRow(
|
| 183 |
column(4, tableOutput("selected_image_captions")),
|
| 184 |
column(4, tableOutput("caption_frequency_table_with_links")),
|
| 185 |
+
column(4, tableOutput("relation_database_display"))
|
| 186 |
)
|
| 187 |
)
|
| 188 |
)
|
|
|
|
| 354 |
# 選択されている画像のcaptionを別変数に保存
|
| 355 |
captions_for_selected_image <- updated_data$caption[updated_data$image_path == input$selected_image]
|
| 356 |
|
| 357 |
+
if (nrow(relation_database()) > 0) {
|
| 358 |
+
for (i in 1:nrow(relation_database())) {
|
| 359 |
+
parent <- relation_database()$parent_caption[i]
|
| 360 |
+
child <- relation_database()$child_caption[i]
|
| 361 |
+
|
| 362 |
+
# parent_captionの存在確認を行い、存在する場合remove_caption_and_adjust_orderを実行
|
| 363 |
+
if (parent %in% captions_for_selected_image) {
|
| 364 |
+
updated_data <- remove_caption_and_adjust_order(updated_data, input$selected_image, child)
|
| 365 |
+
}
|
| 366 |
}
|
| 367 |
}
|
| 368 |
|
|
|
|
| 378 |
observeEvent(input$aggregate_all, {
|
| 379 |
updated_data <- captions_data()
|
| 380 |
|
| 381 |
+
if (nrow(relation_database()) > 0) {
|
| 382 |
+
for (image_path in unique(updated_data$image_path)) {
|
| 383 |
+
# 各画像のcaptionを別変数に保存
|
| 384 |
+
captions_for_image <- updated_data$caption[updated_data$image_path == image_path]
|
|
|
|
|
|
|
|
|
|
| 385 |
|
| 386 |
+
for (i in 1:nrow(relation_database())) {
|
| 387 |
+
parent <- relation_database()$parent_caption[i]
|
| 388 |
+
child <- relation_database()$child_caption[i]
|
| 389 |
+
|
| 390 |
+
# parent_captionの存在確認を行い、存在する場合remove_caption_and_adjust_orderを実行
|
| 391 |
+
if (parent %in% captions_for_image) {
|
| 392 |
+
updated_data <- remove_caption_and_adjust_order(updated_data, image_path, child)
|
| 393 |
+
}
|
| 394 |
}
|
| 395 |
}
|
| 396 |
}
|
|
|
|
| 404 |
update_log("Captions aggregated for all images.")
|
| 405 |
})
|
| 406 |
|
| 407 |
+
observeEvent(input$remove_relation_index, {
|
| 408 |
+
index_to_remove <- as.numeric(input$remove_relation_index)
|
| 409 |
+
|
| 410 |
+
# 削除する関係の情報を保存
|
| 411 |
+
parent_to_remove <- relation_database()$parent_caption[index_to_remove]
|
| 412 |
+
child_to_remove <- relation_database()$child_caption[index_to_remove]
|
| 413 |
+
|
| 414 |
+
# 関係を削除
|
| 415 |
+
relation_database(relation_database()[-index_to_remove, ])
|
| 416 |
+
|
| 417 |
+
# ログを更新
|
| 418 |
+
update_log(paste("Removed relation:", parent_to_remove, "->", child_to_remove))
|
| 419 |
+
})
|
| 420 |
+
|
| 421 |
# Relation Databaseをセーブ
|
| 422 |
output$save_relation_database <- downloadHandler(
|
| 423 |
filename = function() {
|
|
|
|
| 607 |
update_log("MOVE CAPTION ALL MODE.")
|
| 608 |
})
|
| 609 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 610 |
observeEvent(input$confirm_order, {
|
| 611 |
switch(operation_mode(),
|
| 612 |
"add_single" = {
|
|
|
|
| 657 |
showOrderInput(FALSE)
|
| 658 |
})
|
| 659 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
observeEvent(input$cancel_order, {
|
| 661 |
operation_mode("Normal")
|
| 662 |
showOrderInput(FALSE)
|
|
|
|
| 847 |
}
|
| 848 |
}, sanitize.text.function = function(x) x)
|
| 849 |
|
| 850 |
+
output$relation_database_display <- renderTable({
|
| 851 |
+
db <- relation_database()
|
| 852 |
+
|
| 853 |
+
# relation_databaseが空でない場合のみリンクを作成
|
| 854 |
+
if (nrow(db) > 0) {
|
| 855 |
+
db$remove <- sprintf("<a href='javascript:void(0);' onclick='handleCaptionClick(\"%s\", \"remove_RDB\");'>Remove</a>", 1:nrow(db))
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
db
|
| 859 |
+
}, sanitize.text.function = function(x) x) # HTMLをエスケープしないようにする
|
| 860 |
+
|
| 861 |
}
|
| 862 |
|
| 863 |
# アプリを実行
|