diff --git a/package.json b/package.json
index 39b4f26..5a6596c 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"moment": "^2.30.1",
"prom-client": "^15.1.0",
"react": "^18.2.0",
+ "react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
"react-fast-marquee": "^1.6.5",
"react-helmet": "^6.1.0",
diff --git a/src/api/duty.jsx b/src/api/duty.jsx
index 6d1eaaa..25daa62 100644
--- a/src/api/duty.jsx
+++ b/src/api/duty.jsx
@@ -112,6 +112,19 @@ async function searchCalendar(params) {
}
}
+async function GetCalendarUsers(params) {
+ try {
+ const res = await http('get', '/api/w8t/calendar/getCalendarUsers', params);
+ return res;
+ } catch (error) {
+ message.open({
+ type: 'error',
+ content: '获取值班表用户列表失败',
+ });
+ return error
+ }
+}
+
export {
getDutyManagerList,
createDutyManager,
@@ -119,5 +132,6 @@ export {
deleteDutyManager,
createCalendar,
updateCalendar,
- searchCalendar
+ searchCalendar,
+ GetCalendarUsers
}
\ No newline at end of file
diff --git a/src/pages/alert/rule/create.jsx b/src/pages/alert/rule/create.jsx
index 17321d6..8638626 100644
--- a/src/pages/alert/rule/create.jsx
+++ b/src/pages/alert/rule/create.jsx
@@ -73,7 +73,7 @@ export const AlertRule = ({ type }) => {
const [enabled, setEnabled] = useState(true) // 设置初始状态为 true
const [recoverNotify,setRecoverNotify] = useState(true)
const [alarmAggregation,setAlarmAggregation] = useState(true)
- const [selectedType, setSelectedType] = useState(null) // 数据源类型
+ const [selectedType, setSelectedType] = useState(0) // 数据源类型
const [datasourceOptions, setDatasourceOptions] = useState([]) // 数据源列表
const [selectedItems, setSelectedItems] = useState([]) //选择数据源
const [noticeLabels, setNoticeLabels] = useState([]) // noAice Lable
@@ -85,7 +85,7 @@ export const AlertRule = ({ type }) => {
const [severityValue, setSeverityValue] = useState(1)
const [jaegerServiceList, setJaegerServiceList] = useState([])
- const [selectedCard, setSelectedCard] = useState(null);
+ const [selectedCard, setSelectedCard] = useState(0);
const [exprRule, setExprRule] = useState([{}])
// 初始化时间数据的状态
const [week,setWeek] = useState(null)
@@ -144,32 +144,45 @@ export const AlertRule = ({ type }) => {
useEffect(() => {
if (ruleTemplate) {
// 使用模板数据初始化表单
- type = "tmpl";
form.setFieldsValue(ruleTemplate);
- setPromQL(ruleTemplate.prometheusConfig.promQL)
- setExprRule(ruleTemplate.prometheusConfig.rules)
- }
- }, [ruleTemplate]);
-
- useEffect(() => {
- const handleSearchRuleInfo = async ()=>{
- try {
- const params = {
- ruleGroupId: id,
- ruleId: ruleId
- };
- const res = await searchRuleInfo(params);
- setSelectedRow(res.data); // 更新状态
- initBasicInfo(res.data)
- } catch (error) {
- console.error('Error fetching rule info:', error);
- } finally {
- setLoading(false); // 请求完成后设置 loading 状态
+ setPromQL(ruleTemplate.prometheusConfig.promQL);
+ setExprRule(ruleTemplate.prometheusConfig.rules);
+
+ const datasourceTypeMap = {
+ "Prometheus": 0,
+ "Loki": 1,
+ "AliCloudSLS": 2,
+ "Jaeger": 3,
+ "CloudWatch": 4,
+ "VictoriaMetrics": 5,
+ "KubernetesEvent": 6,
+ "ElasticSearch": 7
+ };
+
+ const t = datasourceTypeMap[ruleTemplate.datasourceType] || 0;
+ setSelectedType(t);
+ setSelectedCard(t);
+ type = 'tmpl'
+ } else {
+ const handleSearchRuleInfo = async ()=>{
+ try {
+ const params = {
+ ruleGroupId: id,
+ ruleId: ruleId
+ };
+ const res = await searchRuleInfo(params);
+ setSelectedRow(res.data); // 更新状态
+ initBasicInfo(res.data)
+ } catch (error) {
+ console.error('Error fetching rule info:', error);
+ } finally {
+ setLoading(false); // 请求完成后设置 loading 状态
+ }
}
- }
- if (type === "edit"){
- handleSearchRuleInfo()
+ if (type === "edit"){
+ handleSearchRuleInfo()
+ }
}
}, [])
@@ -1034,7 +1047,7 @@ export const AlertRule = ({ type }) => {
-
diff --git a/src/pages/alert/tmpl/index.jsx b/src/pages/alert/tmpl/index.jsx
index cecc4b9..05e2207 100644
--- a/src/pages/alert/tmpl/index.jsx
+++ b/src/pages/alert/tmpl/index.jsx
@@ -181,6 +181,8 @@ export const RuleTemplate = () => {
ruleGroupName: selectedRuleGroup.label
};
+ console.log(templateData)
+
// 将数据存储到 Context 中
setRuleTemplate(templateData);
diff --git a/src/pages/duty/calendar/CreateCalendar.jsx b/src/pages/duty/calendar/CreateCalendar.jsx
index 5675077..76b02ed 100644
--- a/src/pages/duty/calendar/CreateCalendar.jsx
+++ b/src/pages/duty/calendar/CreateCalendar.jsx
@@ -1,19 +1,35 @@
-import React, { useState } from 'react'
-import { Form, Modal, Divider, InputNumber, DatePicker, Select, Button, message } from 'antd'
+import React, {useEffect, useState} from 'react'
+import {Form, Modal, InputNumber, DatePicker, Select, Button, List, Avatar, Space, Drawer, Input} from 'antd'
+import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'
+import { PlusOutlined, DeleteOutlined, MenuOutlined } from '@ant-design/icons'
import { getAllUsers } from '../../../api/other.jsx'
-import { createCalendar } from '../../../api/duty'
+import {createCalendar, GetCalendarUsers} from '../../../api/duty'
+import Search from "antd/es/input/Search";
export const CreateCalendarModal = ({ visible, onClose, dutyId }) => {
const { Option } = Select
const [form] = Form.useForm()
- const [selectedItems, setSelectedItems] = useState([])
const [selectedMonth, setSelectedMonth] = useState(null)
const [dutyPeriod, setDutyPeriod] = useState(1)
const [filteredOptions, setFilteredOptions] = useState([])
const [dateType, setDateType] = useState('day')
+ const [selectedUsers, setSelectedUsers] = useState([])
+ const [searchVisible, setSearchVisible] = useState(false)
- const handleSelectChange = (_, value) => {
- setSelectedItems(value)
+ useEffect(() => {
+ handleGetCalendarUsers()
+ }, [visible])
+
+ const handleGetCalendarUsers = async () =>{
+ try {
+ const params = {
+ dutyId: dutyId
+ }
+ const res = await GetCalendarUsers(params)
+ setSelectedUsers(res.data)
+ } catch (error) {
+ console.error(error)
+ }
}
const onChangeDate = (date, dateString) => {
@@ -49,19 +65,153 @@ export const CreateCalendarModal = ({ visible, onClose, dutyId }) => {
}
}
+ const onSearchDutyUser = (query) =>{
+ // 确保 query 是一个有效的字符串
+ if (!query || typeof query !== "string") {
+ handleSearchDutyUser()
+ return;
+ }
+
+ // 过滤 filteredOptions
+ const filtered = filteredOptions.filter((item) =>
+ item.username.toLowerCase().includes(query.toLowerCase())
+ );
+
+ // 更新过滤后的结果
+ setFilteredOptions(filtered);
+ }
+
+ const handleDragEnd = (result) => {
+ if (!result.destination) return
+
+ const items = Array.from(selectedUsers)
+ const [reorderedItem] = items.splice(result.source.index, 1)
+ items.splice(result.destination.index, 0, reorderedItem)
+
+ setSelectedUsers(items)
+ }
+
+ const handleDeleteUser = (index) => {
+ const newUsers = selectedUsers.filter((_, idx) => idx !== index)
+ setSelectedUsers(newUsers)
+ }
+
+ const SelectUserModal = () => (
+ setSearchVisible(false)}
+ footer={null}
+ styles={{ body: { maxHeight: 'calc(100vh - 300px)', overflowY: 'auto' } }}
+ >
+
+ !selectedUsers.find(user => user.userid === option.userid)
+ )}
+ renderItem={item => (
+ {
+ setSelectedUsers([...selectedUsers, item])
+ setSearchVisible(false)
+ }}
+ style={{ cursor: 'pointer' }}
+ >
+ {item.username[0]}}
+ title={item.username}
+ />
+
+ )}
+ />
+
+ )
+
+ const DutyUserList = () => (
+
+
+
{
+ handleSearchDutyUser()
+ setSearchVisible(true)
+ }}
+ style={{ marginBottom: 16 }}
+ >
+ 添加值班人员
+
+
+
+
+ {(provided) => (
+
+ {selectedUsers.map((user, index) => (
+
+ {(provided) => (
+
+
+
+
+
+ {user.username[0]}
+ {user.username}
+ }
+ onClick={() => handleDeleteUser(index)}
+ />
+
+
+ )}
+
+ ))}
+ {provided.placeholder}
+
+ )}
+
+
+
+
+ )
const generateCalendar = () => {
- if (selectedMonth && dutyPeriod && selectedItems.length > 0) {
+ if (selectedMonth && dutyPeriod && selectedUsers.length > 0) {
const startDate = new Date(selectedMonth)
const endDate = new Date(startDate)
- endDate.setDate(endDate.getDate() + (dutyPeriod * selectedItems.length) - 1)
+ endDate.setDate(endDate.getDate() + (dutyPeriod * selectedUsers.length) - 1)
const calendarData = {
dutyId: dutyId,
month: selectedMonth,
dutyPeriod: dutyPeriod,
dateType: dateType,
- users: selectedItems.map((item) => ({ username: item.value, userid: item.userid })),
+ users: selectedUsers.map((user) => ({
+ username: user.username,
+ userid: user.userid
+ })),
}
handleFormSubmit(calendarData)
@@ -71,15 +221,7 @@ export const CreateCalendarModal = ({ visible, onClose, dutyId }) => {
}
return (
-
-
-
+
{
/>
-
-
-
+
-
- 提交
-
-
+
+
+ 提交
+
+
+
+
)
}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 7734924..f705f4a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1377,6 +1377,13 @@
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.15.4":
+ version "7.26.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
+ integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6":
version "7.23.8"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650"
@@ -2559,6 +2566,14 @@
dependencies:
"@types/node" "*"
+"@types/hoist-non-react-statics@^3.3.0":
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010"
+ integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
"@types/html-minifier-terser@^6.0.0":
version "6.1.0"
resolved "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
@@ -2655,6 +2670,16 @@
dependencies:
"@types/react" "*"
+"@types/react-redux@^7.1.20":
+ version "7.1.34"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e"
+ integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+ redux "^4.0.0"
+
"@types/react@*":
version "17.0.39"
resolved "https://registry.npmmirror.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce"
@@ -4321,6 +4346,13 @@ css-blank-pseudo@^3.0.3:
dependencies:
postcss-selector-parser "^6.0.9"
+css-box-model@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
+ integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==
+ dependencies:
+ tiny-invariant "^1.0.6"
+
css-declaration-sorter@^6.0.3:
version "6.1.4"
resolved "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4"
@@ -6240,6 +6272,13 @@ he@^1.2.0:
resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
hoopy@^0.1.4:
version "0.1.4"
resolved "https://registry.npmmirror.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
@@ -7836,6 +7875,11 @@ memfs@^3.1.2, memfs@^3.4.1:
dependencies:
fs-monkey "1.0.3"
+memoize-one@^5.1.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
+ integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
+
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
@@ -9266,6 +9310,11 @@ quick-lru@^5.1.1:
resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+raf-schd@^4.0.2:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
+ integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
+
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -9772,6 +9821,19 @@ react-base16-styling@^0.6.0:
lodash.flow "^3.3.0"
pure-color "^1.2.0"
+react-beautiful-dnd@^13.1.1:
+ version "13.1.1"
+ resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2"
+ integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+ css-box-model "^1.2.0"
+ memoize-one "^5.1.1"
+ raf-schd "^4.0.2"
+ react-redux "^7.2.0"
+ redux "^4.0.4"
+ use-memo-one "^1.1.1"
+
react-content-loader@^5.1.3:
version "5.1.4"
resolved "https://registry.npmmirror.com/react-content-loader/-/react-content-loader-5.1.4.tgz#854bafe4415dd9de07174621375bc308edd0ebb5"
@@ -9845,12 +9907,12 @@ react-is@18.2.0, react-is@^18.2.0:
resolved "https://registry.npmmirror.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
-react-is@^16.12.0, react-is@^16.13.1:
+react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
-react-is@^17.0.1:
+react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@@ -9890,6 +9952,18 @@ react-popper@^1.3.6:
typed-styles "^0.0.7"
warning "^4.0.2"
+react-redux@^7.2.0:
+ version "7.2.9"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d"
+ integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==
+ dependencies:
+ "@babel/runtime" "^7.15.4"
+ "@types/react-redux" "^7.1.20"
+ hoist-non-react-statics "^3.3.2"
+ loose-envify "^1.4.0"
+ prop-types "^15.7.2"
+ react-is "^17.0.2"
+
react-refresh@^0.11.0:
version "0.11.0"
resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
@@ -10058,6 +10132,13 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
+redux@^4.0.0, redux@^4.0.4:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
+ integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
regenerate-unicode-properties@^10.0.1:
version "10.0.1"
resolved "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
@@ -11202,6 +11283,11 @@ timsort@^0.3.0:
resolved "https://registry.npmmirror.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==
+tiny-invariant@^1.0.6:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127"
+ integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==
+
tinycolor2@^1.4.1:
version "1.6.0"
resolved "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
@@ -11558,6 +11644,11 @@ use-latest@^1.2.1:
dependencies:
use-isomorphic-layout-effect "^1.1.1"
+use-memo-one@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
+ integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==
+
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"